【不同的子序列II】

题目描述


给定一个字符串 s,计算 s 的 不同非空子序列 的个数。因为结果可能很大,所以返回答案需要对 10^9 + 7 取余 。

字符串的 子序列 是经由原字符串删除一些(也可能不删除)字符但不改变剩余字符相对位置的一个新字符串。

例如,"ace""abcde" 的一个子序列,但 "aec" 不是。

数据样例&给定要求

示例 1:

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

示例 2:

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

示例 3:

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

提示:

1 <= s.length <= 2000
s 仅由小写英文字母组成

题目思路

  1. 这是一道动态规划类型的题目
  2. 子序列问题我们要从以每一个位置作为结尾来进行考虑
  3. 子序列问题每一个位置我们做出俩个决策,选或者不选
  4. 最后子序列的结果就是以每一个字符结尾的所有子序列结果的累加和
  5. 共有26个小写字母,记录以每一个小写字母结尾形成子序列的个数,但是我们可能会出现重复的字母,所以我们通过数组来记录每个字母上一次出现的下标位置,然后求得以当前字母结尾的子序列个数,将所有的结果进行累加求得,最后取模

题目代码

方法一:
class Solution {

    final int mod=1000000007;

    public int distinctSubseqII(String s) {
        char c[]=s.toCharArray();
        long count[]=new long[26];
        for(int i=0;i<c.length;i++){
            int a=c[i]-'a';
            for(int j=0;j<26;j++){
                if(j!=a){
                    count[a]+=count[j];
                }
            }
            count[a]=(count[a]+1)%mod;
        }
        long ans=0;
        for(int i=0;i<26;i++){
            ans+=count[i];
        }
        return (int)(ans%mod);
    }
}
方法二:
class Solution {

    final int mod=1000000007;

    public int distinctSubseqII(String s) {
        int n=s.length();
        int[] res=new int[n];
        int[] arr=new int[26];
        Arrays.fill(res,1);
        Arrays.fill(arr,-1);
        for(int i=0;i<n;i++){
            int index=s.charAt(i)-'a';
            for(int j=0;j<26;j++){
                if(arr[j]>=0){
                    res[i]=(res[i]+res[arr[j]])%mod;
                }
            }
            arr[index]=i;
        }
        int sum=0;
        for(int i=0;i<26;i++){
            if(arr[i]>=0){
                sum=(sum+res[arr[i]])%mod;
            }
        }
        return sum%mod;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

硕风和炜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值