Article / 文章
LeetCode 159 至多包含两个不同字符的最长子串:滑动窗口经典题
给定一个字符串 s,找出 至多 包含两个不同字符的最长子串 t,并返回该子串的长度。
题目描述
给定一个字符串 s,找出 至多 包含两个不同字符的最长子串 t,并返回该子串的长度。
难度
中等
题目链接
示例
示例 1:
输入: s = "eceba"
输出: 3
解释: t 是 "ece",长度为3。
示例 2:
输入: s = "ccaabbb"
输出: 5
解释: t 是 "aabbb",长度为5。
示例 3:
输入: s = "aaaaa"
输出: 5
解释: t 是 "aaaaa",长度为5。
提示
1 <= s.length <= 105s由英文字母组成
解题思路
方法:滑动窗口
使用滑动窗口和哈希表来维护不同字符的计数。 关键点:
- 使用哈希表记录窗口内字符的出现次数
- 当不同字符数超过2时,移动左指针
- 更新最大长度
- 处理边界情况
时间复杂度:O(n),其中n是字符串长度。 空间复杂度:O(1),因为最多存储3个字符的计数。
代码实现
C# 实现
public class Solution {
public int LengthOfLongestSubstringTwoDistinct(string s) {
if (string.IsNullOrEmpty(s)) return 0;
Dictionary<char, int> dict = new Dictionary<char, int>();
int left = 0, maxLen = 0;
for (int right = 0; right < s.Length; right++) {
char c = s[right];
if (!dict.ContainsKey(c)) {
dict[c] = 0;
}
dict[c]++;
while (dict.Count > 2) {
char leftChar = s[left];
dict[leftChar]--;
if (dict[leftChar] == 0) {
dict.Remove(leftChar);
}
left++;
}
maxLen = Math.Max(maxLen, right - left + 1);
}
return maxLen;
}
}
Python 实现
class Solution:
def lengthOfLongestSubstringTwoDistinct(self, s: str) -> int:
if not s:
return 0
char_count = {}
left = max_len = 0
for right, char in enumerate(s):
char_count[char] = char_count.get(char, 0) + 1
while len(char_count) > 2:
left_char = s[left]
char_count[left_char] -= 1
if char_count[left_char] == 0:
del char_count[left_char]
left += 1
max_len = max(max_len, right - left + 1)
return max_len
C++ 实现
class Solution {
public:
int lengthOfLongestSubstringTwoDistinct(string s) {
if (s.empty()) return 0;
unordered_map<char, int> charCount;
int left = 0, maxLen = 0;
for (int right = 0; right < s.length(); right++) {
charCount[s[right]]++;
while (charCount.size() > 2) {
charCount[s[left]]--;
if (charCount[s[left]] == 0) {
charCount.erase(s[left]);
}
left++;
}
maxLen = max(maxLen, right - left + 1);
}
return maxLen;
}
};
性能分析
各语言实现的性能对比:
| 实现语言 | 执行用时 | 内存消耗 | 特点 |
|---|---|---|---|
| C# | 92 ms | 38.2 MB | 实现简洁,性能适中 |
| Python | 156 ms | 16.8 MB | 代码最简洁 |
| C++ | 24 ms | 9.6 MB | 性能最优 |
补充说明
代码亮点
- 使用滑动窗口优化时间复杂度
- 使用哈希表维护字符计数
- 代码结构清晰,易于维护
常见错误
- 没有处理空字符串的情况
- 没有正确处理字符计数为0的情况
- 边界条件处理不当
相关题目
讨论
有几个问题可以思考一下:
- 滑动窗口什么时候需要收缩(左指针右移)?判断条件是什么?
- 如果改成“至多包含K个不同字符”,代码需要改哪里?
- 滑动窗口这个技巧还能用来解决哪些问题?
欢迎在评论区讨论。
如果你都看到这里了,说明还是有点收获的吧?给个赞鼓励一下呗。