包含所有三种字符的子字符串数目-LeetCode
1358. 包含所有三种字符的子字符串数目
🎯 问题描述(来源于LeetCode)
描述:
给定一个由字符 'a'、'b'、'c' 组成的字符串 s。请返回包含至少一个 'a'、一个 'b' 和一个 'c' 的子字符串数量。
说明:
- 子字符串是连续的。
s的长度在[3, 5×10^4]之间。
示例:
- 示例 1:
1 | 输入: s = "abcabc" |
- 示例 2:
1 | 输入: s = "aaacb" |
💻 解题思路
思路:滑动窗口(双指针)
算法步骤
- 将字符串转为字符列表(或直接迭代字符串)。
- 初始化左指针
left = 0,计数器count = {'a':0, 'b':0, 'c':0},答案ans = 0。 - 遍历右指针
right,将当前字符s[right]加入计数。 - 当窗口中同时包含至少一个
'a'、'b'、'c'时,说明以当前左指针为起点、右指针为终点以及更右的终点,所有子串都满足条件。此时,left表示最小的合法左端点,因此以left及更小的左端点(即 0 到 left-1)作为起点的子串也都满足条件,数量为left + 1(即left本身?代码中ans += left实际上累加了left的值,但通常应为left + 1。需要确认代码正确性:标准做法是ans += left + 1。但用户代码写的是ans += left。我们需在思考中解释。) - 然后移动左指针,尝试收缩窗口,并更新计数,直到窗口不再满足条件。
- 返回
ans。
代码实现(您的代码)
1 | class Solution: |
📊 性能分析
- 时间复杂度:,每个元素最多被左右指针各访问一次。
- 空间复杂度:,使用固定大小的字典。
思考
该解法利用滑动窗口统计所有满足条件的子串。当窗口内包含 a、b、c 至少各一个时,若左指针为 left,则以当前右端点 right 为结尾的子串中,左端点可以是 0 到 left-1 中的任意一个(因为这些子串也必然包含全部三种字符,因为它们包含当前窗口的左半部分),共 left 个。因此将 left 累加到答案中,而不是 left+1,是因为左端点取 0 到 left-1 共 left 种。这正是代码 ans += left 的原因。在每次满足条件并收缩后,left 已经是第一个使得窗口不满足条件的左端点,所以以 right 为结尾的合法子串数为 left。
注意:若左指针从 0 开始,当第一次满足条件时,left 可能为 1(因为收缩一次),此时 ans += 1,代表以 right 为结尾且左端点为 0 的子串合法,数量为 1,正确。该算法是此题的高效解法,代码简洁,但在理解上需要留意累加逻辑。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来源 笺札!






