不重複子字串
阿新 • • 發佈:2021-07-18
請從字串中找出一個最長的不包含重複字元的子字串,計算該最長子字串的長度。
示例1:
輸入: "abcabcbb"
輸出: 3
解釋: 因為無重複字元的最長子串是 "abc",所以其長度為 3。
示例 2:
輸入: "bbbbb"
輸出: 1
解釋: 因為無重複字元的最長子串是 "b",所以其長度為 1。
示例 3:
輸入: "pwwkew"
輸出: 3
解釋: 因為無重複字元的最長子串是"wke",所以其長度為 3。
請注意,你的答案必須是 子串 的長度,"pwke"是一個子序列,不是子串
思考
暴力法
首先把子串找出來,然後判斷是否重複。判斷是否重複的過程,如果用遍歷的方法就有點low了,這是主要是一個快速查詢,可以用set,其實和去重差不多。
我的思考
這種題,我一般喜歡看看有沒有dp的解法,一般是考慮以每個字元結尾的結果。以abaab為例
- 如果子串以a結尾,長度為1
- 如果字串以b結尾,判斷b在之前出現過沒,如果沒有,判斷a出現過沒。
- 最後找出最大的長度
參考解法
同學提示了下,他說這個其實可以用滑動視窗,具體過程如下、
- right = 1, left = 0, set維護不重複子串
- left所指向的字元加入set
- right所指向的字元如果在set , 說明重複出現,開始計算長度,並把left++, 暴力解法中right執行需要回退到left + 1處,把set清空進入下一次迴圈。但是我們可以進行優化,就是left移動前的對應的元素給刪除了,right不變。現在想想,這其實是利用了不重複子串的left指標前移一次仍然是不重複的,所以沒有必要回退。
- 這裡程式碼有個坑,當迴圈結束後,還要比較一次set裡的長度和當前長度。如'aq'
class Solution { public int lengthOfLongestSubstring(String s) { // fast = 1 slow = 0 //1. slow 加到map // 2. 觀察fast是否可以在map中,如果不再,則fast++,否則slow ++ ,統計長度, slow裡面要刪除. 滑動視窗 if (s == null || s.length() == 0) { return 0; } char[] chars = s.toCharArray(); int left = 0; int right = 1; int len = s.length(); int result = 1; Set<Character> set = new HashSet<>(); set.add(chars[left]); while(right < len) { char curChar = chars[right]; if (set.contains(curChar)) { // 統計長度 result = Math.max(result, right - left); set.remove(chars[left]); left++; } else { set.add(curChar); right++; } } result = Math.max(result, set.size()); return result; } }