[LeetCode] 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: tis "ece" which its length is 3.
Example 2:
Input: "ccaabbb"
Output: 5
Explanation: tis "aabbb" which its length is 5.
这道题给我们一个字符串,让求最多有两个不同字符的最长子串。那么首先想到的是用 HashMap 来做,HashMap 记录每个字符的出现次数,然后如果 HashMap 中的映射数量超过两个的时候,这里需要删掉一个映射,比如此时 HashMap 中e有2个,c有1个,此时把b也存入了 HashMap,那么就有三对映射了,这时 left 是0,先从e开始,映射值减1,此时e还有1个,不删除,left 自增1。这时 HashMap 里还有三对映射,此时 left 是1,那么到c了,映射值减1,此时e映射为0,将e从 HashMap 中删除,left 自增1,然后更新结果为 i - left + 1,以此类推直至遍历完整个字符串,参见代码如下:
解法一:
class Solution {
public:
int lengthOfLongestSubstringTwoDistinct(string s) {
int res = , left = ;
unordered_map<char, int> m;
for (int i = ; i < s.size(); ++i) {
++m[s[i]];
while (m.size() > ) {
if (--m[s[left]] == ) m.erase(s[left]);
++left;
}
res = max(res, i - left + );
}
return res;
}
};
我们除了用 HashMap 来映射字符出现的个数,还可以映射每个字符最新的坐标,比如题目中的例子 "eceba",遇到第一个e,映射其坐标0,遇到c,映射其坐标1,遇到第二个e时,映射其坐标2,当遇到b时,映射其坐标3,每次都判断当前 HashMap 中的映射数,如果大于2的时候,那么需要删掉一个映射,还是从 left=0 时开始向右找,看每个字符在 HashMap 中的映射值是否等于当前坐标 left,比如第一个e,HashMap 此时映射值为2,不等于 left 的0,那么 left 自增1,遇到c的时候,HashMap 中c的映射值是1,和此时的 left 相同,那么我们把c删掉,left 自增1,再更新结果,以此类推直至遍历完整个字符串,参见代码如下:
解法二:
class Solution {
public:
int lengthOfLongestSubstringTwoDistinct(string s) {
int res = , left = ;
unordered_map<char, int> m;
for (int i = ; i < s.size(); ++i) {
m[s[i]] = i;
while (m.size() > ) {
if (m[s[left]] == left) m.erase(s[left]);
++left;
}
res = max(res, i - left + );
}
return res;
}
};
后来又在网上看到了一种解法,这种解法是维护一个 sliding window,指针 left 指向起始位置,right 指向 window 的最后一个位置,用于定位 left 的下一个跳转位置,思路如下:
1. 若当前字符和前一个字符相同,继续循环。
2. 若不同,看当前字符和 right 指的字符是否相同
(1) 若相同,left 不变,右边跳到 i - 1
(2) 若不同,更新结果,left 变为 right+1,right 变为 i - 1
最后需要注意在循环结束后,还要比较结果 res 和 s.size() - left 的大小,返回大的,这是由于如果字符串是 "ecebaaa",那么当 left=3 时,i=5,6 的时候,都是继续循环,当i加到7时,跳出了循环,而此时正确答案应为 "baaa" 这4个字符,而我们的结果 res 只更新到了 "ece" 这3个字符,所以最后要判断 s.size() - left 和结果 res 的大小。
另外需要说明的是这种解法仅适用于于不同字符数为2个的情况,如果为k个的话,还是需要用上面两种解法。
解法三:
class Solution {
public:
int lengthOfLongestSubstringTwoDistinct(string s) {
int left = , right = -, res = ;
for (int i = ; i < s.size(); ++i) {
if (s[i] == s[i - ]) continue;
if (right >= && s[right] != s[i]) {
res = max(res, i - left);
left = right + ;
}
right = i - ;
}
return max(s.size() - left, res);
}
};
还有一种不使用 HashMap 的解法,是在做 Fruit Into Baskets 这道题的时候在论坛上看到的,其实这两道题除了背景设定之外没有任何的区别,代码基本上都可以拷来直接用的。这里使用若干的变量,其中 cur 为当前最长子串的长度,first 和 second 为当前候选子串中的两个不同的字符,cntLast 为 second 字符的连续长度。遍历所有字符,假如遇到的字符是 first 和 second 中的任意一个,那么 cur 可以自增1,否则 cntLast 自增1,因为若是新字符的话,默认已经将 first 字符淘汰了,此时候选字符串由 second 字符和这个新字符构成,所以当前长度是 cntLast+1。然后再来更新 cntLast,假如当前字符等于 second 的话,cntLast 自增1,否则均重置为1,因为 cntLast 统计的就是 second 字符的连续长度。然后再来判断若当前字符不等于 second,则此时 first 赋值为 second, second 赋值为新字符。最后不要忘了用 cur 来更新结果 res,参见代码如下:
解法四:
class Solution {
public:
int lengthOfLongestSubstringTwoDistinct(string s) {
int res = , cur = , cntLast = ;
char first, second;
for (char c : s) {
cur = (c == first || c == second) ? cur + : cntLast + ;
cntLast = (c == second) ? cntLast + : ;
if (c != second) {
first = second; second = c;
}
res = max(res, cur);
}
return res;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/159
类似题目:
Longest Substring Without Repeating Characters
Longest Substring with At Most K Distinct Characters
Subarrays with K Different Integers
参考资料:
https://leetcode.com/problems/longest-substring-with-at-most-two-distinct-characters/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] 159. Longest Substring with At Most Two Distinct Characters 最多有两个不同字符的最长子串的更多相关文章
- [LeetCode] 340. Longest Substring with At Most K Distinct Characters 最多有K个不同字符的最长子串
Given a string, find the length of the longest substring T that contains at most k distinct characte ...
- [LeetCode] Longest Substring with At Most Two Distinct Characters 最多有两个不同字符的最长子串
Given a string S, find the length of the longest substring T that contains at most two distinct char ...
- [LeetCode] Longest Substring with At Most K Distinct Characters 最多有K个不同字符的最长子串
Given a string, find the length of the longest substring T that contains at most k distinct characte ...
- [leetcode]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 char ...
- ✡ leetcode 159. Longest Substring with At Most Two Distinct Characters 求两个字母组成的最大子串长度 --------- java
Given a string, find the length of the longest substring T that contains at most 2 distinct characte ...
- 395 Longest Substring with At Least K Repeating Characters 至少有K个重复字符的最长子串
找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k .输出 T 的长度.示例 1:输入:s = "aaabb", k = 3输出:3最 ...
- leetcode[159] Longest Substring with At Most Two Distinct Characters
找到最多含有两个不同字符的子串的最长长度.例如:eoeabc,最长的是eoe为3,其他都为2. 思路: 用p1,p2表示两种字符串的最后一个出现的下标位置.初始p1为0. p2为-1.start初始化 ...
- [leetcode]340. Longest Substring with At Most K Distinct Characters至多包含K种字符的最长子串
Given a string, find the length of the longest substring T that contains at most k distinct characte ...
- 【LeetCode】159. Longest Substring with At Most Two Distinct Characters
Difficulty: Hard More:[目录]LeetCode Java实现 Description Given a string S, find the length of the long ...
随机推荐
- 小小见解之python循环依赖
a.py from b import b print '---------this is module a.py----------' def a(): print "hello, a&qu ...
- redis的3种过期键删除策略
Redis的过期键的过期时间都保存在过期字典中,过期键的删除策略有三种,分别是定时删除.惰性删除和定期删除. 定时删除 定时删除策略,是指在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时 ...
- 【题解】Ples [COCI2011]
[题解]Ples [COCI2011] 依旧是没有传送门,只有提供了数据的官网. [题目描述] \(N\) 个汉子和 \(N\) 个妹纸一起参加舞会,跳舞时只能是一个汉子一个妹纸配对,现在给出每个人的 ...
- Python学习之路 【目录】
* Python之路[楔子]:PyCharm 专业版安装 * Python之路[第一篇]:Python简介和入门 * Python之路[第二篇]:Python基础(一 ...
- python with语句与contextlib
参考链接:https://www.ibm.com/developerworks/cn/opensource/os-cn-pythonwith/ with语句用于异常处理,适用于存在资源访问的场合,无论 ...
- EntityUtils.toString(entity)处理字符集问题解决
爬取51Job和猎聘网的信息,想处理字符集问题(51job为gbk,猎聘为utf-8), 找到两个网站字符集信息都在同一标签下 就想先把网页保存成String,解析一遍获取字符集,然后将网页转换成对应 ...
- jQuery AJAX方法详谈
AJAX是与服务器交换数据并更新部分网页的技术,而无需重新加载整个页面. 下表列出了所有jQuery AJAX方法: 方法 描述 $.ajax() 执行异步AJAX请求 $.ajaxPrefilter ...
- jQuery 选择器有61种你都知道了多少
下面列举了61种jQuery 选择器 参考 选择器 语句 描述 * $("*") 选择所有元素 #id $("#lastname") id=“lastname” ...
- windows7系统 执行应用程序报 Error accessing specified device (Error: 2)
--------------------------- ---------------------------Error accessing specified device (Error: 2) - ...
- FCC-学习笔记 Convert HTML Entities
FCC-学习笔记 Convert HTML Entities 1>最近在学习和练习FCC的题目.这个真的比较的好,推荐给大家. 2>中文版的地址:https://www.freecode ...