1. 程式人生 > >[LeetCode] 3. Longest Substring Without Repeating Characters(無重複字元的最長子串)-滑動視窗法

[LeetCode] 3. Longest Substring Without Repeating Characters(無重複字元的最長子串)-滑動視窗法

本題是 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: