[LeetCode] 1358. Number of Substrings Containing All Three Characters 包含所有三种字符的子字符串数目


Given a string s consisting only of characters ab and c.

Return the number of substrings containing at least one occurrence of all these characters ab and c.

Example 1:

Input: s = "abcabc"
Output: 10
Explanation: The substrings containing at least one occurrence of the characters ab and c are "abc", "abca", "abcab", "abcabc", "bca", "bcab", "bcabc", "cab", "cabc" and "abc" (again).

Example 2:

Input: s = "aaacb"
Output: 3
Explanation: The substrings containing at least one occurrence of the characters ab and c are "aaacb", "aacb" and "acb".

Example 3:

Input: s = "abc"
Output: 1

Constraints:

  • 3 <= s.length <= 5 x 10^4
  • s only consists of ab or *c *characters.

这道题给了一个只有 a,b,c 三个字母构成的字符串s,现在让找出三个字母均至少出现一次的子串的个数。一般玩字符串的题目无外乎就是滑动窗口 Sliding Window 和动态规划 Dynamic Programming 用的比较多。这道题不太适合用 DP,状态转移方程不太好找。来看看能否用滑动窗口来做吧,如果题目让求的是三个字母都只出现一次的话,想必大家应该都没啥问题,这里的至少出现一次也算是个难点了,就拿例子1来分析,当滑动窗口套住第一个 abc 的时候,此时除了其本身是符合要求的,其后面的每个字母都可以跟窗口里的字母组成符合要求的子串,组成 abca, abcab, abcabc,这样统计的个数世纪上就是 n-i,n是原字符串s的总长度,i是当前滑动窗口的右边界,整个步骤如下所示:

[a b c] a b c
abc, abca, abcab, ababc

a [b c a] b c
bca, bcab, bcabc

a b [c a b] c
cab, cabc

a b c [a b c]
abc

通过上面这种计数方法,我们就可以不重复的统计出所有满足情况的子串。当然这种统计方法也不是唯一的,比如 lee215 大神用的就是另一种统计方法,其主要是统计左边界前面的字母个数,也是可以的,参见代码如下:


解法一:

class Solution {
public:
    int numberOfSubstrings(string s) {
        int res = 0, n = s.size(), left = 0;
        vector<int> cnt(3);
        for (int i = 0; i < n; ++i) {
            ++cnt[s[i] - 'a'];
            while (cnt[0] && cnt[1] && cnt[2]) {
                res += n - i;
                --cnt[s[left++] - 'a'];
            }
        }
        return res;
    }
};

再来看一种更加简洁的解法,这里记录 a,b,c 最后出现的位置,初始化为-1,然后每次取其中最小的数字,再加上1就是当前范围内符合要求的子串的个数。当最小值为初始的 -1 时,说明某个字母没有出现过,则加上0不影响结果,而当最小的大于等于0了,说明每个字母都出现过了,而最小的那个值就相当于滑动窗口的左边界,其实还是统计左边界前面的字母个数,参见计数过程如下:

a b c a b c

i = 0, [0, -1, -1], min = -1
i = 1, [0, 1, -1], min = -1
i = 2, [0, 1, 2], min = 0 -> abc
i = 3, [3, 1, 2], min = 1 -> abca, bca
i = 4, [3, 4, 2], min = 2 -> abcab, bcab, cab
i = 5, [3, 4, 5], min = 3 -> abcabc, bcabc, cabc, abc

解法二:

class Solution {
public:
    int numberOfSubstrings(string s) {
        int res = 0, n = s.size();
        vector<int> last(3, -1);
        for (int i = 0; i < n; ++i) {
            last[s[i] - 'a'] = i;
            res += 1 + min({last[0], last[1], last[2]});
        }
        return res;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1358


类似题目:

Vowels of All Substrings


参考资料:

https://leetcode.com/problems/number-of-substrings-containing-all-three-characters

https://leetcode.com/problems/number-of-substrings-containing-all-three-characters/solutions/516977/java-c-python-easy-and-concise/

https://leetcode.com/problems/number-of-substrings-containing-all-three-characters/solutions/3459766/explained-w-images-made-easy-c/


LeetCode All in One 题目讲解汇总(持续更新中...)

posted @   Grandyang  阅读(160)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
历史上的今天:
2017-10-30 [LeetCode] 713. Subarray Product Less Than K 子数组乘积小于K
2016-10-30 [LeetCode] 438. Find All Anagrams in a String 找出字符串中所有的变位词
2015-10-30 [CareerCup] 13.3 Virtual Functions 虚函数
2015-10-30 [CareerCup] 13.2 Compare Hash Table and STL Map 比较哈希表和Map
2014-10-30 ASCII Table - ASCII码对照表
2014-10-30 Resources
2014-10-30 PixelFormat 像素格式
Fork me on GitHub

喜欢请打赏

扫描二维码打赏

Venmo 打赏

点击右上角即可分享
微信分享提示