159. Longest Substring with At Most Two Distinct Characters
Given a string s , find the length of the longest substring t that contains at most 2 distinct characters.
Example 1:
Input: "eceba"
Output: 3
Explanation: t is "ece" which its length is 3.
Example 2:
Input: "ccaabbb"
Output: 5
Explanation: t is "aabbb" which its length is 5.
方法1: hash + index
思路:
用hashmap来维持每个字符出现的最后位置,当hash.size() < 2 时,可以直接加入。双指针right指向的位置如果是一个出现过的字符,可以直接更新该字符的最后坐标。反之如果是一个新的字符,而此时hash的size已经== 2,我们需要找到当前两个字符中最早结束的那个。怎么寻找呢?通过移动left,要意识到只有字母出现的最后一次满足hash[s[left]] == left。掌握了这一点,只要用一个内循环找到这个位置,删除left的字符,left再右移一位,就可以了。
易错点
- 如何识别“最早结束的字符”这一点不好想到,最后也别忘left++
- 不要忘了把right添加到hash里
Complexity
Time complexity: O(n)
Space complexity: O(1), hash始终不超过3个entry
class Solution {
public:
int lengthOfLongestSubstringTwoDistinct(string s) {
int result = 0;
int left = 0;
unordered_map<char, int> hash;
for (int right = 0; right < s.size(); right++){
// 还有余量
if (hash.size() < 2){
hash[s[right]] = right;
}
else {
if (hash.count(s[right]) == 0){
hash[s[right]] = right;
while (hash[s[left]] != left) left ++;
hash.erase(s[left]);
left ++;
}
else {
hash[s[right]] = right;
}
}
result = max(result, right - left + 1);
}
return result;
}
};
方法2: hash + count
grandyang: http://www.cnblogs.com/grandyang/p/5185561.html
思路:
这种方法和上面的区别是,并不记录index,而是对每个字符计数。那么左指针在舍弃左边的时候就需要依次将hash值–,这里循环条件也相对与上面被精简:先无脑推入新的字符,如果多出来了再去电,而内循环中只要erase这一步还没有发生,left就会一直向右移动。
Complexity
Time complexity: O(n)
Space complexity: O(1)
class Solution {
public:
int lengthOfLongestSubstringKDistinct(string s, int k) {
if (k == 0) return 0;
int result = 0;
unordered_map<char, int> hash;
int left = 0;
for (int right = 0; right < s.size(); right++){
++hash[s[right]];
while(hash.size() > k){
if (--hash[s[left]] == 0) hash.erase(s[left]);
left++;
}
result = max(result, right - left + 1);
}
return result;
}
};
// s = "e c e b a", k = 2
// l
// r
// hash = {a:4, b: 3}
// result = 3