1. 程式人生 > >位元組跳動2018.9.9筆試 最長不重複子串

位元組跳動2018.9.9筆試 最長不重複子串

題目描述

給定一個字串,請找出其中無重複字元的最長子字串的長度。例如,“abcabcbb”,其無重複字元的最長子字串實“abc”,其長度為3。“bbbbb”,其無重複字元的最長子字串是“b”,長度為1。 此題是leetcode第三題原題。

本人思路

這裡寫圖片描述 以上圖為例,已經掃描到了abc了: 如果迴圈到了字元a,與當前掃描到的字串中的a重複了,那麼新的字串就應該從a之後開始到當前迴圈字元。 如果迴圈到了字元b,與當前掃描到的字串中的b重複了,那麼新的字串就應該從b之後開始到當前迴圈字元。 … 如果迴圈到了字元d,與當前掃描到的字串中每個字元都不重複,那麼新的字串就應該從起始位置到當前迴圈字元。

程式碼

s = input()
n = len(s)

temp = []#儲存當前掃描到的無重複最長子串
maxleng = 0 

for i in range(n):
    if(s[i] not in temp):#如果不在temp裡就新增進去
        temp.append(s[i])
    else:#如果在裡面,檢視temp的長度是否比maxleng大
        if len(temp)>maxleng:
            maxleng = len(temp)
        index = temp.index(s[i])#獲得當前重複的索引
temp = temp[index+1:len(temp)]#新的temp是從重複字元之後開始 temp.append(s[i])#再添加當前重複字元 if len(temp)>maxleng:#計算最後一次 maxleng = len(temp) print(maxleng)

但此程式碼有個弊端,就是需要temp陣列來存當前掃描到的無重複子串,實際是不需要的。

最優思路

上LeetCode提交我的程式碼,執行時間124ms,打敗了44%的人,可見我這個演算法之差啊。但由於我提交的程式碼是python3,在LeetCode裡面也只能看見python3裡面的最優程式碼(80ms),下面我將對最優程式碼進行講解。

class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        start, longest, store = 0, 0, {}
        for i, c in enumerate(s):
            if c not in store:
                store[c] = i
            else:#當前c已經出現過了,但不一定在當前掃描到的無重複子串中
                #記錄下當前c之前位置掃描到無重複子串的長度
                longest = max(longest, i - start)
                #更新無重複子串的開始位置,為下一次記錄作好準備
                #如果當前c不在當前掃描到的無重複子串中,start不會更新
                start = max(start, store[c] + 1)
                #更新每個字元的最新位置
                store[c] = i
        longest = max(longest, len(s) - start)#記錄最後一次
        return longest

此程式碼相比我的程式碼,優點在於不需要temp陣列儲存當前掃描到無重複子串,而是用start記錄無重複子串的開始索引。

但是程式碼的思想和我的是很類似的。

和最優程式碼的進入else的條件不一樣,我是在temp裡有重複的就進入,所以無重複子串的起始位置肯定會更新;最優程式碼是隻有字元是第二次出現就進入else,但不一定會更新無重複子串的起始位置。

start索引記錄無重複子串的起碼位置,i記錄的是i-1是無重複子串的終止位置。我的程式碼中,是根據當前字元是否與temp有重複,如果有就進入else,進入else後起始位置start必更新。最優程式碼中,是根據當前字元是否出現過,如果出現過就進入else,進入else後起始位置start不一定更新,因為有可能當前字元上一次出現索引在start前面,這樣的話start就不會更新。

start更新後,就為下一次進入else作好了準備,下一次執行longest = max(longest, i - start)i - start則就是下一次掃描到的無重複子串的長度。

再分析終止位置吧,當迴圈變數到了i時,終止位置則為I-1,看我畫的第一個圖就能明白。