5325包含所有三种字符的子字符串数目

题目:给你一个字符串 s ,它只包含三种字符 a, b 和 c 。请你返回 a,b 和 c 都 至少 出现过一次的子字符串数目。

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

法一:自己的代码

思路:刚开始的思路是利用类似戳气球的方法,dp[i][j]表示字符串中从i到j的符合条件的字符串的个数,进而推导从dp[i+1][j]和dp[i][j-1]如何计算出dp[i][j],但是前面两个有重复的部分,推理很复杂,难以用dp进行记录,考虑改变dp的定义,dp[i][j]表示字符串中从0到i,a b c最后一次出现的索引,而以字符s[i]结尾的满足条件的子字符串的个数,即最小索引的值加一,

class Solution:
    def numberOfSubstrings(self, s: str) -> int:
        size = len(s)
        dp = [[-1] * (size+1) for i in range(3)]
        d = {'a':0, 'b':1, 'c':2}
        res = 0
        for col in range(1, size+1):
            for row in range(3):
                dp[row][col] = dp[row][col-1]
            dp[d[s[col-1]]][col]  = col - 1
            r = min(dp[0][col], dp[1][col], dp[2][col])
            if r != -1:
                res += (r+1)
        return res
View Code

改进后的dp数组,只需更新三个值即可

class Solution:
    def numberOfSubstrings(self, s: str) -> int:
        d = {'a':0, 'b':0, 'c':0}
        res = 0
        for i,j in enumerate(s):
            d[j] = i + 1
            print(d)
            # a b c 的最小值即字符串中以s[i]结尾的满足条件的子字符串的个数
            res += min(d.values())
        return res
if __name__ == '__main__':
    solution = Solution()
    # result = solution.numberOfSubstrings(s = "abcabcccccc")
    result = solution.numberOfSubstrings(s = "aaabbbccc")
    # result = solution.numberOfSubstrings(s = "aaabc")
    print(result)
View Code

法二:双指针法

思路:我们使用首尾指针维护一个滑动窗口。
    如果窗口内没有 aaa,bbb,ccc,尾指针右移来寻找字符直到窗口内包含 aaa,bbb,ccc;
    如果窗口内包含 aaa,bbb,ccc,当窗口继续向右拉开时肯定仍然包含 aaa,bbb,ccc,所以直接加上窗口右侧到末尾的距离;
    然后左侧指针右移,每移动一步进行以上两种情况的判读即可。
之所以用这个解法是因为,确定一个字符串只需要知道两个因素,即左边的索引和右边的索引,这里的双指针法实际上是分类讨论,先让左指针不动,移动右指针,一旦找到满足条件的,再移动左指针,

posted on 2020-02-24 11:27  吃我一枪  阅读(394)  评论(0编辑  收藏  举报

导航