[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 ...
随机推荐
- web.xml引入 xml (tomcat 7.0.52) 以上版本报错
原文地址:https://blog.csdn.net/sdmxdzb/article/details/47728017?locationNum=11 今天在搞工作流,tomcat7.0.57 总是报错 ...
- LeetCode 155:最小栈 Min Stack
LeetCode 155:最小栈 Min Stack 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈. push(x) -- 将元素 x 推入栈中. pop() -- ...
- paramiko 远程执行多个命令
转发博客如下 https://blog.csdn.net/c_base_jin/article/details/86561445
- CSS3 clip裁剪动画
CSS3 clip裁剪动画 下面是比较简单的例子 <pre><html><head><style type="text/css">i ...
- SpringDataRedis入门Demo
步骤: 约定>配置>代码 在pom.xml中导入依赖(redis和jedis以及其他所需的依赖) > 配置相关配置文件(redis-config.properties 和applic ...
- 基本认证(Basic Authorization)
---------------------------------- import arcpy from base64 import encodestring username = 'xxx' pas ...
- webform的原生操作图片预览和上传
1.使用input标签进行图片操作,input的标签有一个accept属性,accept 属性只能与 <input type="file"> 配合使用.它规定能够通过文 ...
- laravel Method Illuminate\Validation\Validator::validateReuqired does not exist.
Method Illuminate\Validation\Validator::validateReuqired does not exist. 此错误是由于我们在配置验证时,写错了关键字, publ ...
- 分布式Redis深度历险-Cluster
本文为分布式Redis深度历险系列的第三篇,主要内容为Redis的Cluster,也就是Redis集群功能. Redis集群是Redis官方提供的分布式方案,整个集群通过将所有数据分成16384个槽来 ...
- 前端之:js
JavaScript概述 ECMAScript和JavaScript的关系 1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组织ECM ...