Given a string s, find the length of the longest substring without repeating characters.

Example 1:

Input: s = “abcabcbb” Output: 3 Explanation: The answer is “abc”, with the length of 3. Example 2:

Input: s = “bbbbb” Output: 1 Explanation: The answer is “b”, with the length of 1. Example 3:

Input: s = “pwwkew” Output: 3 Explanation: The answer is “wke”, with the length of 3. Notice that the answer must be a substring, “pwke” is a subsequence and not a substring.

解題思路:

題目主要是找出 依序且不重複的最長字串。

pwwkew 可以找出 wke 是最長的字串。

看起來不難,所以寫了一個錯的解法…


def lengthOfLongestSubstring(s):
    index = 0
    sub_string = ""
    max_length = 1

    while True:
        if s[index] not in sub_string:
            sub_string += s[index]
        else:
            max_length = max(max_length, len(sub_string))
            sub_string = s[index]
        index += 1

        if index >= len(s):
            break
    return max(max_length, len(sub_string))

思路是,把這選取到的字串放在 sub_string 中,如果遇到重複的字串,就把目前的 sub_string 與 max_length 比較,如果 sub_string 比較長,就更新 max_length。

看起來很正常,畢竟 “abcabcbb” 就是 “abc” 、 “pwwkew” 就是 “wke”。 都是拿重複那個字之後的字串繼續跑,Submit 之後才發現,如果是 dvdf 就爆了,這演算法只會找到 dvdf,但實際答案是 vdf

所以正解應該是要用 滑動窗口 的方式來解題。 正確思路是這樣的…

我們給予一個陣列稱 walked 好了,這陣列會記錄現在走過的字元 然後我們給予兩個指標 leftrightleft 代表目前的字串的開頭,right 代表目前的字串的結尾 透過 right 來遍歷整個字串,如果 s[right] 不在 walked

這時會發現,如果 walkeds[right] 走過了該怎麼辦?

d v d f
l   r

當 r 在 d 上,walked 裡又有 d 時,我們就必須讓 left 走到沒有 d 的地方(walked 也要隨著修正成[v]),這樣就不重複了!

d v d f
  l r

最後找出 walked 的最大長度即可。

def lengthOfLongestSubstring(s):
    left = 0
    right = 0
    max_length = 0

    walked = []
    while right < len(s):
        while (s[right] in walked):
            walked.pop(0)
            left += 1
        walked.append(s[right])

        max_length = max(max_length, len(walked))
        right += 1
    return max_length