加载中...
1358-包含所有三种字符的子字符串数目(Number of Substrings Containing All Three Characters)
发表于:2021-12-03 | 分类: 中等
字数统计: 1.1k | 阅读时长: 4分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/number-of-substrings-containing-all-three-characters

英文原文

Given a string s consisting only of characters a, b and c.

Return the number of substrings containing at least one occurrence of all these characters a, b 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 a, b or 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 。

通过代码

高赞题解

首先最朴素的想法:枚举所有的子串,然后检查是否符合条件。不过这个时间效率是 O(n^3),过于低下。那是哪里有浪费和冗余呢?

为了更好的说明问题,我们稍稍修改一下样例 1,在前面再加个 “a”,即:"aabcabc"
image.png
image.png
我们依旧傻傻的进行枚举,首先是 "a",不符合。再是 "aa",不符合。再是 "aab" ,不符合。然后终于出现了满足的条件的子串,"aabc"。(上图)

继续枚举:"aabca",符合。”aabcab",符合。诶等等,真的还需要再枚举吗???当第一次发现 “aabc” 这个符合条件的子串时,它右边所有拓展出来的串都是符合条件的。 "aabc" 的右边可以扩展出 4 个串(包括自己),答案加4。

如果把我们枚举范围看成一个窗口,我们刚刚从index=0开始,向右扩展窗口找到了第一个符合条件的字符串"aabc"。很容易发现,"aabc"是符合条件的,左边去掉一个”a”之后的后缀字符串"abc"也是符合条件的。(下图)
image.png
为了找到这些可能符合条件的后缀,我们不断向右收缩窗口的左沿,直至不符合条件"aabc"收缩成"abc",符合,答案再加 4。"abc"收缩成"bc",不符合,停止收缩。(上图)

此时,窗口左沿为 index=2,窗口右沿为 index=3,以 index=3 结尾的所有字符串我们已经找完了。下一步,向右拓展窗口右沿,找到新的符合条件的字符串"bca",(当然如果不符合条件就继续拓展,直至符合条件)。符合条件后,又像刚才那样开始向右收缩窗口左沿。
image.png

重复以上步骤。

值得一提的是,为了判断当前窗口(或者说字符串)是不是符合条件的,肯定是需要对 abc 分别计数的。而每一个字符串都去遍历每个字符来计数的话也太慢了,我们需要充分利用移动窗口前的计数信息,在之前的基础上相应的计数+1/-1。
image.png

附上双百代码

class Solution {
    public int numberOfSubstrings(String s) {
        int answer=0;
        //abc 的计数
        int[] count=new int[3];
        //窗口左沿
        int start=0;
        //窗口右沿
        for(int end=0;end<s.length();end++){
            char charAtEnd=s.charAt(end);
            count[charAtEnd-'a']++;
            while(count[0]>=1 && count[1]>=1 && count[2]>=1){
                answer+=s.length()-end;
                char charAtStart=s.charAt(start);
                count[charAtStart-'a']--;
                start++;
            } 
        }
        return answer;
    }
}

统计信息

通过次数 提交次数 AC比率
6232 12594 49.5%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
1356-根据数字二进制下 1 的数目排序(Sort Integers by The Number of 1 Bits)
下一篇:
1337-矩阵中战斗力最弱的 K 行(The K Weakest Rows in a Matrix)
本文目录
本文目录