[M雙指標] lc3. 無重複字元的最長子串(雙指標)
阿新 • • 發佈:2020-12-14
文章目錄
1. 題目來源
2. 題目解析
方法一:雙指標
很經典的一個雙指標演算法。如何將一個暴力演算法優化成雙指標演算法呢?主要是需要找到單調性。簡單聊一下從暴力到雙指標的這個過程:
- 暴力演算法: 兩層迴圈,列舉第
i
個位置的字母,再列舉[0, i]
位置,這樣就能列舉得到以i
位置結尾的所有子串。將合法的子串記錄下來,長度取個max
即可。時間複雜度是 O ( n 2 ) O(n^2) O(n2) 的。 - 雙指標演算法: 假設子串終點位置為
i
j
與當前這個i
位置一一對應。當i
向後移動時,j
就不可能再向前移動了,因為若j - 1
和i + 1
構成了合法情況。那麼,j - 1
也一定能和i
構成合法情況。這個違反了j
的定義。故j
實際上是不可能再向前移動的,它最多隻能保持不動或者發生重複情況向後移動。故j
具有單調性。那麼當我們順序列舉i
時,起初i
和j
都在首字元,即起點 0 的位置,當i ++
時,若不發生重複,則j
不需要向後移動。若發生重複,則只可能是s[i]
這個字元和s[j~i - 1]
這個區間中的某個字元發生重複,因為j
不能向前移動!所以,就一直向後移動j
i
位置的最靠左的j
位置,即對於i
的最佳且合法的子串起點位置。
這個是很經典很經典的雙指標演算法。十分有利於理解雙指標演算法的本質,且思路並不是那麼好想。很值得學習~
時間複雜度:
O
(
n
)
O(n)
O(n)
空間複雜度:
O
(
n
)
O(n)
O(n)
程式碼:
class Solution {
public:
int lengthOfLongestSubstring(string s) {
unordered_map<char, int> hash;
int res = 0;
for (int i = 0, j = 0; i < s.size(); ++i) {
// 將當前字元新增進雜湊表中
hash[s[i]]++;
// 雙指標如果雜湊表中字元重複出現了,只可能是s[i]重複
// 就將j指標一直向前刪除,直到刪了這個重複字元
// 並將該重複字元在雜湊表的數量減1
// 精髓在於 hash[s[j++]]--; 雜湊表維護[j,i]區間內的所有字元的出現次數,實現O(1)的查詢
while (um[s[i]] > 1) hash[s[j++]]--;
res = max(res, i - j + 1);
}
return res;
}
};