题目描述
思路
我们列出如下三个定义
显然最终答案应该是dp[n-1][2]。all right,怎么进行状态转移呢?
你发现,只有遇到了0才能更新dp[i][0];只有遇到1才能更新dp[i][1];只有遇到2才能更新dp[i][2]。
- 如果
nums[i]==0, 意味着前面长度为i-1的序列后面添了一个0,这不会影响到“先0后1”的序列数量,也不会影响“先0中1后2”的序列数量。那么dp[i][0]怎么更新呢?dp[i][0]可以被看成三部分的组合- 假装没有新来的0,那么”全0“的序列数量为
dp[i-1][0] - 旧”全0序列“中每个方案都搭配上这个新来的0,序列数量也是
dp[i-1][0] - 旧”全0序列“方案全不要,只留这个新来的0,方案数为1
- 综上,
dp[i][0] = dp[i-1][0] * 2 + 1
- 假装没有新来的0,那么”全0“的序列数量为
- 如果
nums[i]==1, 意味着前面长度为i-1的序列后面添了一个1,这不会影响到”全0序列”数量,也不会影响”先0中1后2“的序列数量。那么dp[i][1]怎么更新呢?dp[i][1]可以被看成三部分的组合- 假装没有新来的1,那么“先0后1”的序列数量为
dp[i-1][1] - 旧”先0后1序列“中每个方案都搭配上这个新来的1,序列数量也是
dp[i-1][1] - 旧的1全不要,只留这个新来的1,那么“先0后1”的方案数为
dp[i-1][0] - 综上,
dp[i][1] = dp[i-1][1] * 2 + dp[i-1][0]
- 假装没有新来的1,那么“先0后1”的序列数量为
- 如果
nums[i]==2, 意味着前面长度为i-1的序列后面添了一个2,这不会影响到”全0序列”数量,也不会影响“先0后1”的序列数量。那么dp[i][2]怎么更新呢?dp[i][2]可以被看成三部分的组合- 假装没有新来的2,那么”先0中1后2“的序列数量为
dp[i-1][2] - 旧”先0中1后2序列“中每个方案都搭配上这个新来的2,序列数量也是
dp[i-1][2] - 旧的2全不要,只留这个新来的2,那么"先0中1后2"的方案数为
dp[i-1][1] - 综上,
dp[i][2] = dp[i-1][2] * 2 + dp[i-1][1]
- 假装没有新来的2,那么”先0中1后2“的序列数量为
代码
class Solution:
def countSpecialSubsequences(self, nums: List[int]) -> int:
MOD = int(1e9+7)
dp = [0] * 3
for x in nums :
if x == 0 :
dp[0] = (dp[0] * 2 + 1) % MOD
elif x == 1 :
dp[1] = (dp[1] * 2 + dp[0]) % MOD
else :
dp[2] = (dp[2] * 2 + dp[1]) % MOD
return dp[2]