題目出處
https://leetcode.com/problems/longest-substring-without-repeating-characters/
難度
Medium
題目分類
HashTable, TwoPointers, String, SlidingWindow
個人範例程式碼 - 2022/4/27
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if not s:
return 0
fast = 0
window_element = set()
max_length = 0
for slow in range(len(s)):
while fast < len(s) and s[fast] not in window_element:
window_element.add(s[fast])
max_length = max(max_length, len(window_element))
fast += 1
window_element.remove(s[slow])
return max_length
最近在練習程式碼本身就可以自解釋的 Coding style,可以嘗試直接閱讀程式碼理解
算法說明
使用 sliding window 的概念,我們需要使用 同向的 pointer,
思路很簡單,我們透過建立一個 window_element,裡面代表著現在我們鎖定的元素範圍,
而兩個 pointer:
- fast,走在前,不斷收集不重複元素
- slow,走在後,當無法蒐集不重複元素時,開始邊移動,並移除 window 的元素
input handling
如果沒有 s,return 0
Boundary conditions
搜尋至 len(s) 的範圍,
兩個 pointer 用 for-loop, while 來判斷範圍
個人解法筆記 - 2021/3/31
個人範例程式碼
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
if len(s) == 0:
ans = 0
else:
ans = 0
queue_list = []
l = 0 # left pointer
for r in range(len(s)): # s[r], get one new word
# found duplicate in sliding window, remove until duplicate not found
while s[r] in queue_list:
queue_list.pop(0)
l += 1
# not found or all duplicate removed, push new word s[r]
queue_list.append(s[r])
# update answer
ans = max(ans, r-l+1)
return ans
sliding window
正如其名,移動的窗戶,也就是表示在 window 範圍內必須符合我們要的答案。
two pointers
我們建立兩個指標 l,r,
r 是正常的向前搜尋,
l 是當目前 l,r 所框出的 window 範圍出現不符合題目要求時,「反覆」移動 l 直到 window 符合題目要求。
示意圖:(r先跑,l依照條件變化而跑)

示意圖:(l依照條件變化而跑,為了符合條件)
我們可以發現當下長度 = (r-l) + 1

HashTable
示意圖:(用 Queue 來儲存已存在的 window 中的字)
在搜尋目前 window 是否符合條件時,我們需要建立一個 HashTable,幫助我們速查特定值是否存在表裡面,
我們建立的 HashTable 也需要達到 Queue 的功能 (因為隨著 l 的移動,會有先進先出的問題),
我們可以看到,當 b 進來時,我們必須一直丟到 Queue 裡面沒有 b 為止,「才是正確的 window 」

Reference
https://leetcode.com/problems/longest-substring-without-repeating-characters/discuss/1134357/O(n)-Time-and-Space-Sliding-Window
https://www.youtube.com/watch?v=wiGpQwVHdE0