LeetCode 1358.包含所有三种字符的子字符串数目:滑动窗口(两种写法直接推荐方法二)

【LetMeFly】1358.包含所有三种字符的子字符串数目:滑动窗口(两种写法直接推荐方法二)

力扣题目链接:https://leetcode.cn/problems/number-of-substrings-containing-all-three-characters/

给你一个字符串 s ,它只包含三种字符 a, b 和 c 。

请你返回 a,b 和 c 都 至少出现过一次的子字符串数目。

示例 1:

复制代码
输入:s = "abcabc"
输出:10
解释:包含 a,b 和 c 各至少一次的子字符串为 "abc", "abca", "abcab", "abcabc", "bca", "bcab", "bcabc", "cab", "cabc" 和 "abc" (相同字符串算多次)。

示例 2:

复制代码
输入:s = "aaacb"
输出:3
解释:包含 a,b 和 c 各至少一次的子字符串为 "aaacb", "aacb" 和 "acb" 。

示例 3:

复制代码
输入:s = "abc"
输出:1

提示:

  • 3 <= s.length <= 5 x 10^4
  • s 只包含字符 a,b 和 c 。

解题方法:滑动窗口

使用两个指针,时刻满足指针之间的"窗口"是最短的同时包含abc的窗口。

滑动方法一:枚举窗口起点l(l 到 r-1以及r的右边 全合法)------推荐方法二

两个指针,每次左指针 l l l右移一位,不断右移右指针 r r r直到窗口 [ l , r ) [l, r) [l,r)中含有三种字母。

那么对于起点 l l l,其到 r − 1 r-1 r−1合法到话,其到 r r r、 r + 1 r+1 r+1、 ⋯ \cdots ⋯、 n − 1 n-1 n−1(共计 n − r + 1 n-r+1 n−r+1个)都合法。

滑动方法二:枚举窗口终点r(l-1以及l-1的左边 到 r 全合法)

两个指针,每次右指针 r r r右移一位,不断右移左指针 l l l直到首次满足 窗口 l , r l, r l,r中不含有三种字母。

那么 l − 1 , r l-1, r l−1,r、 l − 2 , r l-2, r l−2,r、 ⋯ \cdots ⋯、 0 , r 0, r 0,r(如果存在)(共计l个)均合法。

时空复杂度分析

  • 时间复杂度 O ( l e n ( s ) ) O(len(s)) O(len(s)),每个字母最多被遍历两次
  • 空间复杂度 O ( 1 ) O(1) O(1)

AC代码

C++------方法二

cpp 复制代码
/*
 * @LastEditTime: 2026-07-01 15:38:27
 */
class Solution {
public:
    int numberOfSubstrings(string s) {
        int ans = 0;
        int cnt[3] = {0};
        for (int l = 0, r = 0, n = s.size(); r < n; r++) {
            cnt[s[r] - 'a']++;
            while (cnt[0] && cnt[1] && cnt[2]) {
                cnt[s[l++] - 'a']--;
            }
            ans += l;
        }
        return ans;
    }
};

C++------方法一

cpp 复制代码
/*
 * @LastEditTime: 2026-07-01 15:34:43
 */
class Solution {
public:
    int numberOfSubstrings(string s) {
        int ans = 0;
        int cnt[3] = {0};
        for (int l = 0, r = 0, n = s.size(); l < n; l++) {
            while (r < n && !(cnt[0] && cnt[1] && cnt[2])) {
                cnt[s[r++] - 'a']++;
            }
            // printf("l = %d, r = %d, cnt = {%d, %d, %d}, ans += %d\n", l, r, cnt[0], cnt[1], cnt[2], n - r + 1);
            ans += (cnt[0] && cnt[1] && cnt[2]) ? n - r + 1 : 0;
            cnt[s[l] - 'a']--;
        }
        return ans;
    }
};

Python------方法二

python 复制代码
'''
LastEditTime: 2026-07-01 15:49:11
'''
class Solution:
    def numberOfSubstrings(self, s: str) -> int:
        ans = 0
        cnt = [0, 0, 0]
        l = r = 0
        for r in range(len(s)):
            cnt[ord(s[r]) - ord('a')] += 1
            while cnt[0] and cnt[1] and cnt[2]:
                cnt[ord(s[l]) - ord('a')] -= 1
                l += 1
            ans += l
        return ans

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~

千篇源码题解已开源

相关推荐
ZhengEnCi8 小时前
Agent 架构怎么选:从单 Agent 到多 Agent 编排的选型决策指南
算法·架构
秋天的怀念_David9 小时前
第二十二夜 · 数字迷雾
java·程序人生·算法
Pniubi9 小时前
力扣283移动零(双指针法)
算法·leetcode·职场和发展
hhb_6189 小时前
大模型落地三重优化实战
人工智能·算法·机器学习
云和数据.ChenGuang10 小时前
光哥说Python RAG 系统需要哪些评估指标:从检索到生成的全链路评测指南
网络·人工智能·python·算法·langchain
2601_9707038311 小时前
工业除湿机租赁:把一份租金合同拆开看
大数据·数据结构·算法·数据库架构·推荐算法
心中有你021411 小时前
Java实现Dijkstra最短路径算法(邻接表 + 优先队列)
java·数据库·算法
ZhengEnCi12 小时前
同样的模型,为什么本地和云 API 差别那么大:量化精度、聊天模板与采样参数的三大元凶
人工智能·算法·llm
Flynn Liang13 小时前
RAG 答非所问/幻觉怎么破?Spring AI QuestionAnswerAdvisor 召回优化实战(TopK/重排/混合检索)
人工智能·算法·spring·rag·幻觉·springai
liminla!13 小时前
SQL 从入门到进阶:语法速查与实战练习(完整优化版)
数据库·sql·算法