1955. 统计特殊子序列的数目 周赛 力扣(困难) 动态规划

1955. 统计特殊子序列的数目

特殊序列 是由 正整数 个 0 ,紧接着 正整数 个 1 ,最后 正整数 个 2 组成的序列。

比方说,[0,1,2] 和 [0,0,1,1,1,2] 是特殊序列。
相反,[2,1,0] ,[1] 和 [0,1,2,0] 就不是特殊序列。
给你一个数组 nums (仅 包含整数 0,1 和 2),请你返回 不同特殊子序列的数目 。由于答案可能很大,请你将它对 109 + 7 取余 后返回。

一个数组的 子序列 是从原数组中删除零个或者若干个元素后,剩下元素不改变顺序得到的序列。如果两个子序列的 下标集合 不同,那么这两个子序列是 不同的 。

示例 1:

输入:nums = [0,1,2,2]
输出:3
解释:特殊子序列为 [0,1,2,2],[0,1,2,2] 和 [0,1,2,2] 。

题解:https://leetcode-cn.com/problems/count-number-of-special-subsequences/solution/dong-tai-gui-hua-by-endlesscheng-4onu/

f[i][0] 表示前 i 项得到的全 0 子序列个数

f[i][1] 表示前 i 项得到的先 0 后 1 的子序列个数

f[i][2] 表示前 i 项得到的特殊子序列个数

若 j =nums[i] 则需要分类计算:

当遇到 0 时,有选或不选两种方案,不选 0 时有 f[i][0] = f[i-1][0],选 0 时,可以单独组成一个子序列,也可以与前面的 0 组合,因此有 f[i][0] = f[i-1][0] + 1,两者相加得 f[i][0] = 2⋅f[i−1][0]+1。

当遇到 1 时,有选或不选两种方案,不选 1 时有 f[i][1] = f[i−1][1],选 1 时,可以单独与前面的 0 组成一个子序列,也可以与前面的 1 组合,因此有 f[i][1] = f[i-1][1] + f[i-1][0],两者相加得 f[i][1]=2⋅f[i−1][1]+f[i−1][0]。

当遇到 2 时,有选或不选两种方案,f[i][2] 和 f[i][1] 类似,有 f[i][2]=2⋅f[i−1][2]+f[i−1][1]。

最后答案为 f[n-1][2]f[n−1][2]。

代码: (可以再压缩一下,只和上一个状态相关,用三个变量即可)

class Solution {
public:
    int countSpecialSubsequences(vector<int>& nums) {
     long long dp[100005][3];
     long long mod=1e9+7;
     dp[0][0]=0;
     dp[0][1]=0;
     dp[0][2]=0;
     if (nums[0]==0) dp[0][0]=1;
     for(int i=1;i<nums.size();i++)
     {
         if(nums[i]==0) 
         {
             dp[i][0]=(dp[i-1][0]*2+1)%mod; 
             dp[i][1]=dp[i-1][1];
             dp[i][2]=dp[i-1][2];
         }
         if(nums[i]==1)
         {
             dp[i][0]=dp[i-1][0];
             dp[i][1]=(dp[i-1][0]+dp[i-1][1]*2)%mod;
             dp[i][2]=dp[i-1][2];
         }
         if(nums[i]==2)
         {
             dp[i][0]=dp[i-1][0];
             dp[i][1]=dp[i-1][1];
             dp[i][2]=(dp[i-1][1]+dp[i-1][2]*2)%mod;
         }
     }
     
     return dp[nums.size()-1][2]%mod;
    }
};
class Solution {
public:
    int countSpecialSubsequences(vector<int>& nums) {
    long long mod=1e9+7;
    long long f[3];
    f[0]=0;f[1]=0;f[2]=0;
    for (auto v:nums) 
    {
        if (v == 0) f[0] = (f[0]*2 + 1) % mod;
          else if (v == 1) f[1] = (f[1]*2 + f[0]) % mod;
             else   f[2] = (f[2]*2 + f[1]) % mod;
        
    }
    return f[2];
    }
};

 

posted on 2021-08-02 20:04  Yxter  阅读(159)  评论(0)    收藏  举报

导航