LeetCode 1987. 不同的好子序列数目--动态规划

  1. 不同的好子序列数目

给你一个二进制字符串 binary 。 binary 的一个 子序列 如果是 非空 的且没有 前导 0 (除非数字是 “0” 本身),那么它就是一个 好 的子序列。

请你找到 binary 不同好子序列 的数目。

比方说,如果 binary = "001" ,那么所有 好 子序列为 ["0", "0", "1"] ,所以 不同 的好子序列为 "0" 和 "1" 。 注意,子序列 "00" ,"01" 和 "001" 不是好的,因为它们有前导 0 。

请你返回 binary 中 不同好子序列 的数目。由于答案可能很大,请将它对 109 + 7 取余 后返回。

一个 子序列 指的是从原数组中删除若干个(可以一个也不删除)元素后,不改变剩余元素顺序得到的序列。

示例 1:

输入:binary = “001”
输出:2
解释:好的二进制子序列为 [“0”, “0”, “1”] 。
不同的好子序列为 “0” 和 “1” 。

示例 2:

输入:binary = “11”
输出:2
解释:好的二进制子序列为 [“1”, “1”, “11”] 。
不同的好子序列为 “1” 和 “11” 。

示例 3:

输入:binary = “101”
输出:5
解释:好的二进制子序列为 [“1”, “0”, “1”, “10”, “11”, “101”] 。
不同的好子序列为 “0” ,“1” ,“10” ,“11” 和 “101” 。

提示:

1 <= binary.length <= 105
binary 只含有 '0' 和 '1' 。

题解

和有趣的题目,我们定义dp[maxn][2],dp[i][0]表示选择了0-i的数字,然后构成结尾为0的好子序列的数目,dp[i][1]就表示结尾为1的好子序列数目。

那么为了去重,我们就认为每次都在给前面的子序列添加新的尾部,重而保证了不会重复。

那么如果nums[i]==0,那么

dp[i][0] = dp[i-1][1] + dp[i-1][0];
dp[i][1] = dp[i-1][1];

这个应该很好理解,如果是nums[i]==1,那么

dp[i][1] = dp[i-1][1] + dp[i-1][0] + 1;//因为1开头可以开启新的符合条件的子序列。
dp[i][0] = dp[i-1][0];

最后再判断下有没有0,单独加个1就行。

AC代码

class Solution {
public:
    typedef long long ll;
    ll dp[100010][2];
    ll mod=1000000007;
    int numberOfUniqueGoodSubsequences(string binary) 
    {
        memset(dp,0,sizeof(dp));
        int ans=0;
        for(int i=0;i<binary.length();i++)
        {
            if(binary[i]=='0')
            {
                dp[i+1][0]=dp[i][1]+dp[i][0];
                dp[i+1][1]=dp[i][1];
                ans = 1;
            }
            else
            {
                dp[i+1][1]=dp[i][1]+dp[i][0]+1;
                dp[i+1][0]=dp[i][0];
            }
            dp[i+1][0]%=mod;
            dp[i+1][1]%=mod;
        }
        return (dp[binary.length()][0] + dp[binary.length()][1]+ans)%mod;
    }
};

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值