Leetcode 940:不同的子序列 II(最详细的解法!!!)

版权声明:本文为博主原创文章,未经博主允许不得转载。有事联系:[email protected] https://blog.csdn.net/qq_17550379/article/details/84105392

给定一个字符串 S,计算 S 的不同非空子序列的个数。

因为结果可能很大,所以返回答案模 10^9 + 7.

示例 1:

输入:"abc"
输出:7
解释:7 个不同的子序列分别是 "a", "b", "c", "ab", "ac", "bc", 以及 "abc"。

示例 2:

输入:"aba"
输出:6
解释:6 个不同的子序列分别是 "a", "b", "ab", "ba", "aa" 以及 "aba"。

示例 3:

输入:"aaa"
输出:3
解释:3 个不同的子序列分别是 "a", "aa" 以及 "aaa"。

提示:

  1. S 只包含小写字母。
  2. 1 <= S.length <= 2000

解题思路

我们首先想到的思路是暴力破解,通过控制抽取S中元素个个数,得到不同的组合,最后计算所有组合的总数。

from itertools import combinations
class Solution:
    def distinctSubseqII(self, S):
        """
        :type S: str
        :rtype: int
        """
        S, result = list(S), list()
        count = 0
        count += len(set(S))
        if len(S) >= 2:
            for i in range(2,len(S)+1):
                result.append(set(combinations(S, i)))
        
        for i in result:
            for _ in i:
                count += 1

        return count%(10**9 + 7)

但是很明显这种做法不可取,太慢了。我们以这个思路为起点,如果我们想要计算S的所有不同子序列个数,我们只需要知道除去最后一个元素的s[:-2]所有不同子序列个数k,那么我们最后的结果就是2k-以s[-1]结尾的所有子序列。现在我们的问题就变成了,怎么计算以s[-1]结尾的所有子序列?如果我们当前要考虑的元素,如S[-1],和之前的所有元素都不同,那么之前必然不会有以s[-1]结尾的所有子序列。如果之前出现过当前考虑的元素的话,那么以s[-1]结尾的所有子序列的个数就是最近一次以s[-1]结尾的所有子序列。例如

a a a
    |

此时,我们知道我们之前的序列有aaa" "。现在我们要将a加上,也就是我们会有2*3=6个子序列,但是之前序列中以a结尾的序列有两个,所以我们的最后结果就是6-2=4。但是因为我们最后不考虑" ",所以还要减去1

class Solution:
    def distinctSubseqII(self, S):
        """
        :type S: str
        :rtype: int
        """
        pos, mod, cur_sum = [0]*26, 1e9+7, 1
        for c in S:
            old_sum = cur_sum
            cur_sum = (cur_sum*2 - pos[ord(c) - 97]) % mod
            pos[ord(c) - 97] = old_sum
        return cur_sum - 1

还可以这样去思考,我们遍历输入的S,例如

a b a
|

此时,我们碰到的以a结尾的字符串只有a。然后

a b a
  |

此时,以b结尾的字符串有abb,也就是a+b" "+b(上一次的结果加上b)。(这其实就是trie

a b a
    |

此时,以a结尾的字符串有ababaaaa,也就是ab+ab+aa+a" "+a(上一次的结果加上a)。所以我们最后的结果就是以ab结尾的字符串个数总和。

实现上,我们需要建立一个26大小的数组以容纳不同字母结尾的字符串个数。每当我们遍历到一个新的字母时,此时我们只要将数组中所有结果加起来然后再加1即为以新的字母为结尾的字符串总数。最后我们只要将数组中的结果加起来即可。

class Solution:
    def distinctSubseqII(self, S):
        """
        :type S: str
        :rtype: int
        """
        end = [0] * 26
        for c in S:
            end[ord(c) - 97] = sum(end) + 1
        return sum(end) % (10**9 + 7)

reference:

https://leetcode.com/problems/distinct-subsequences-ii/discuss/192017/C++JavaPython-4-lines-O(N)-Time-O(1)-Space

https://www.geeksforgeeks.org/count-distinct-subsequences/

我将该问题的其他语言版本添加到了我的GitHub Leetcode

如有问题,希望大家指出!!!

猜你喜欢

转载自blog.csdn.net/qq_17550379/article/details/84105392