Leetcode 面試題48. 最長不含重複字符的子字符串

請從字符串中找出一個最長的不包含重複字符的子字符串,計算該最長子字符串的長度。

示例 1:

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

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

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


提示:

s.length <= 40000

題解:

1) 使用雙指針方法,在字符串上滑動;

2) 當沒有遇到重複字符時,右指針右移

3) 當遇到重複字符時, 左指針移動,移動到重複字符的下一個;

即如註釋中所述,

abcedfc 當遇到第二個c時,將map中的a、b擦掉,並將左指針移動到e處,那麼左指針如何知道要移動到哪裏呢?通過索引字典即可得知。

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        if(s.size()<=1) return s.size();
        map<char,int> record;
        int left = 0, right = 0;
        int max_length = 0;
        while (left < s.size()){
            // 將窗口內的字符存到map中,並將right指針右移
            // 當下一個字符已經在map中時,退出循環
            while ((right<s.size()) && (record.count(s[right])==0)){
                record[s[right]] = right;
                max_length = max(max_length,right-left+1);                  
                right++;
            }
            if(right==s.size())break;

            //退出循環後,則表明right當前所指的字符已經在map中存在
            // 1) 將已存在的字符之前的字符全部erase擦除
            // 如 abcedfc 當遇到第二個c時,將ab擦掉
            // 2) 將已存在的字符對應的索引更新
            int pre_index = record[s[right]];
            auto iter = record.begin();
            while(iter!=record.end()){
                if (iter->second<pre_index)
                    iter = record.erase(iter);
                else iter++;
            }

            // 將left,即左指針移動到當前重複字符的下一個
            left=pre_index+1;
            record[s[right]]=right;
            right++;
            if (right==s.size()) break;
        }
        return max_length;
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章