1. 程式人生 > 其它 >[M雙指標] lc3. 無重複字元的最長子串(雙指標)

[M雙指標] lc3. 無重複字元的最長子串(雙指標)

技術標籤:LeetCode雙指標LeetCode

文章目錄

1. 題目來源

連結:lc3. 無重複字元的最長子串

2. 題目解析

方法一:雙指標

很經典的一個雙指標演算法。如何將一個暴力演算法優化成雙指標演算法呢?主要是需要找到單調性。簡單聊一下從暴力到雙指標的這個過程:

  • 暴力演算法: 兩層迴圈,列舉第 i 個位置的字母,再列舉 [0, i] 位置,這樣就能列舉得到以 i 位置結尾的所有子串。將合法的子串記錄下來,長度取個 max 即可。時間複雜度是 O ( n 2 ) O(n^2) O(n2) 的。
  • 雙指標演算法: 假設子串終點位置為 i
    ,那麼一定有一個最靠左的子串起點 j 與當前這個 i 位置一一對應。當 i 向後移動時,j 就不可能再向前移動了,因為若 j - 1i + 1 構成了合法情況。那麼,j - 1 也一定能和 i 構成合法情況。這個違反了 j 的定義。故 j 實際上是不可能再向前移動的,它最多隻能保持不動或者發生重複情況向後移動。故 j 具有單調性。那麼當我們順序列舉 i 時,起初 ij 都在首字元,即起點 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; } };