無重復字符的最長子串


給定一個字符串,請你找出其中不含有重復字符的 最長子串 的長度。

示例 1:

輸入: "abcabcbb"
輸出: 3
解釋: 因為無重復字符的最長子串是 "abc",所以其長度為 3。
示例 2:

輸入: "bbbbb"
輸出: 1
解釋: 因為無重復字符的最長子串是 "b",所以其長度為 1。
示例 3:

輸入: "pwwkew"
輸出: 3
解釋: 因為無重復字符的最長子串是 "wke",所以其長度為 3。
  請注意,你的答案必須是 子串 的長度,"pwke" 是一個子序列,不是子串。

 

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        int maxlen = 0;
        int curlen = 0;
        unordered_map<char,int> charMap;

        for(int i = 0; i < s.size(); i++){
            if(charMap.find(s[i]) == charMap.end()){
                charMap[s[i]] = i+1;
                curlen += 1;
            }
            else{
                curlen = min(i+1 - charMap[s[i]], curlen+1);
                charMap[s[i]] = i+1;
            }
            maxlen = maxlen < curlen ? curlen : maxlen;
        }

        return maxlen;
    }
};

解題思路:
我是這么思考的:以 s[i] 結尾的子串跟以 s[i-1] 結尾的子串有什么關系?

假設我們已知以 s[i-1] 結尾的無重復字符最長子串的長度,那么對於以 s[i] 結尾的子串來說,無非就是兩種可能:

1. s[i] 曾出現過

2. s[i] 未曾出現過

情況1簡單啊,那就在前者長度的基礎上+1唄

情況2我們要稍微討論一下:

(1)如果 s[j] = s[k] = s[i],j < k < i,也就是說前面的子串出現過兩次 s[i] 了,那么計算以 s[i] 為結尾的最長無重復字符子串長度時,我們肯定是拿 s[i] 跟s[k] 來計算,而不會拿 s[j]。這意味着我們可以用一個hashmap存儲字符的位置,並且在每次出現重復字符的時候,更新hashmap。

(2)如果前面出現過 s[i],那我們計算長度的時候是不是直接 i - k 就好了呢?當然不是,因為 k 到 i 之間的這個子串可能還有其他字符的重復字符,比如: “abba”。

假設我們用 lastlen 和 curlen 分別記錄以 s[i-1],s[i] 結尾的最長無重復字符子串的長度

那么 curlen = min(lastlen+1, i - k)

因為如果 k 到 i 之間的子串出現重復字符了,那么 i - k 肯定大於 lastlen + 1,此時我們要用 lastlen 來計算 curlen,而不能拿 i 和 k來計算

如果k 到 i 之間的子串沒有出現重復字符,那么 i - k 會等於 lastlen + 1,所以取最小值是ok的。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM