[LeetCode] 3. Longest Substring Without Repeating Characters(無重複字元的最長子串)-滑動視窗法
阿新 • • 發佈:2018-12-11
本題是 amazon、Adobe、yelp、Bloomberg的面試題。
問題描述:
方法一:滑動視窗法
解題思路:
①設定兩個滑動指標 i 和 j,區間 s[ i ... j ]為滑動視窗:
②滑動指標j,
③知道遇到了重複的字元:
此時記錄沒有重複字串的長度。
④然後將左指標 i 向右滑動,知道沒有重複字元
Note:我們定義一個數組freq[256]來記錄重複字元,如果freq[256] = 1,表示有一個重複字元, freq[256] = 0,表示沒有重複字元。
實現程式碼:
// 時間複雜度: O(len(s)) // 空間複雜度: O(len(charset)) class Solution { public: int lengthOfLongestSubstring(string s) { int freq[256] = { 0 }; int l = 0, r = -1; //滑動視窗為s[l...r] int res = 0; // 整個迴圈從 l == 0; r == -1 這個空視窗開始 // 到l == s.size(); r == s.size()-1 這個空視窗截止 // 在每次迴圈裡逐漸改變視窗, 維護freq, 並記錄當前視窗中是否找到了一個新的最優值 while (l < s.size()) { if (r + 1 < s.size() && freq[s[r + 1]] == 0) { ++r; freq[s[r]] ++; //元素 s[r] 出現的頻率 + 1 } else //r已經到頭 || freq[s[r+1]] == 1 { freq[s[l]] --; //元素 s[l] 出現的頻率 - 1 l++; } res = max(res, r - l + 1); } return res; } }; int main() { cout << Solution().lengthOfLongestSubstring("abcabcbb") << endl; //3 cout << Solution().lengthOfLongestSubstring("bbbbb") << endl; //1 cout << Solution().lengthOfLongestSubstring("pwwkew") << endl; //3 cout << Solution().lengthOfLongestSubstring("c") << endl; //1 cout << Solution().lengthOfLongestSubstring("") << endl; //0 getchar(); return 0; }
方法二、改進的滑動視窗法
int lengthOfLongestSubstring(string s) { vector<int> dict(256, -1); int maxLen = 0, start = -1; for (int i = 0; i != s.length(); i++) { if (dict[s[i]] > start) start = dict[s[i]]; dict[s[i]] = i; maxLen = max(maxLen, i - start); } return maxLen; }
Explanation:
在初始狀態,定義一個向量 vector<int> dict(256, -1); vector的大小為256,每個數定義初始化為-1;
①當 i = 0時 ,
②當 i = 1 時;
③當 i = 2時;
③ 當 i = 3 時;
此時,dict[ a ] > start;
然後將start 指標移動到重複元素 a 的位置:(塗色部分為視窗)
④當 i = 4 ,
⑤ 當 i = 5 時,
⑥當 i = 6 時,
⑦當 i = 7時,
整個陣列遍歷完成。
Reference: