請從字符串中找出一個最長的不包含重複字符的子字符串,計算該最長子字符串的長度。
示例 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;
}
};