1. 程式人生 > 實用技巧 >LeetCode第3題題解:無重複字元的最長子串

LeetCode第3題題解:無重複字元的最長子串

LeetCode第3題:無重複字元的最長子串


Ps:本系列文章只為記錄自己刷LeetCode過程中的解題過程和思路。


題目來源,LeetCode

題目描述:

給定一個字串,請你找出其中不含有重複字元的最長子串的長度。

示例 1:

輸入: "abcabcbb"

輸出: 3

解釋: 因為無重複字元的最長子串是 "abc",所以其長度為 3。

示例 2:
輸入: "bbbbb"

輸出: 1

解釋: 因為無重複字元的最長子串是 "b",所以其長度為 1。

示例 3:

輸入: "pwwkew"

輸出: 3

解釋: 因為無重複字元的最長子串是"wke",所以其長度為 3。

請注意,你的答案必須是 子串 的長度,"pwke"是一個子序列,不是子串。


解題過程和思路:

這道題的題目很明確,就是找序列中的無重複字元的最長子串。暴力解法的思路很簡單:遍歷序列,假設序列中的每個字元都可能為所求最長子串的第一個字元,每個字元都往後遍歷得到最長的子串,總共可以得到n個子串,最後比較各子串的長度即可。然而,偷偷看了大佬們的做法之後,發現了一個滑動視窗很巧妙的應用:每次發現重複肯定是視窗中已有不重複序列中的某個字元和新探索的字元重複發生了衝突,那麼每次在發生衝突的時候將視窗中的那個字元以及之前的字元踢出滑動視窗即可,視窗每滑動一步便記錄當前視窗大小和歷史視窗大小的長度,大者為當前探索得到的最長子串長度。待視窗滑動到序列的最右端,我們也可以找出最長子串的長度了。(同樣地可以用字典來建模,提高在視窗中重複節點的搜尋速度。


解題收穫:

滑動視窗的應用,記住啦。


程式碼展示

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        # 滑動視窗解法
        """
        :type s: str
        :rtype: int
        """
        max_l = 0 # 記錄目前搜尋到的最大字串長度
        p1 = p2 = 0 # 雙指標指示滑動視窗的兩端,視窗內的字串長度為 p2-p1
        d = {} # 利用字典記錄目前搜尋到的元素,用來查詢是否有重複(將元素值作為鍵值,用字典查詢快啊)

        for index, c in enumerate(s): # 遍歷一遍字串
            if c not in d:     
                d[c] = index   # 如果當前字元不在字典中就加入,鍵值為元素值
                p2 += 1 # 視窗右指標向右滑動1格
            else:
                if d[c] + 1 > p1: # 兩個指標都只能往右移動,如果不是很懂,“abba” 人工模擬這種情況即可
                    p1 = d[c] + 1 # 右指標移動到重複的元素的右邊一位,將左邊的重複元素踢出視窗
                p2 += 1 # 右指標繼續往右滑動1格
                d[c] = index # 字典記錄重複元素的最新的索引值
            max_l = max(p2-p1, max_l) # 對比當前最大長度和歷史最大長度,替換歷史最大長度
        return max_l


結果展示