其他分享
首页 > 其他分享> > 552. Student Attendance Record II

552. Student Attendance Record II

作者:互联网

比较难的dp问题。由于A最多出现一次,我们先不考虑A,只考虑存在L和P的情况,最后插入A。

dp[i][0] 前i个且最后为L,dp[i][1] 前i个且最后为P

递推公式如下

dp[i][0] 说明当前最后是L,那么前面可能是L或者A。前面如果是L,那么再前面只能是A,所以是 dp[i-2][1];如果前面是A,就是 dp[i-1][1]。

所以 dp[i][0] = dp[i-1][1] + dp[i-2][1]

dp[i][1] = dp[i-1][0] + dp[i-1][1],没什么特别的,因为如果最后是A,前面是什么都可以。

Base Case

dp[1][0]=dp[1][1]=1;   dp[2][0]=dp[2][1]=2; 

我们定义 dp[0][0]=0,dp[0][1]=1,最后循环插入A的时候会更加方便,同时 dp[2][0]也可以包括在dp的循环中。

至此,如果给定长度为i,那么不包含A的所有可能字符串的总数为 dp[i][0]+dp[i][1]

最后的答案包含两种情况:

1. 不包含A,dp[n][0]+dp[n][1]

2. 包含A,由于只能有一个A,A可以出现在任何位置。用一个循环枚举A的位置,左边总数*右边总数即可,(dp[i][0]+dp[i][1]) * (dp[n-1-i][0]+dp[n-1-i][1])

由于base case里 dp[0][0]=0,dp[0][1]=1,因此 dp[0][0]+dp[0][1]=1,i=0和n-1的边界条件也包括了进去。

class Solution {
public:
    long long MOD = 1e9 + 7;
    
    int checkRecord(int n) {
        vector<vector<long long>> dp(n+1,vector<long long>(2,0));
        // there is no absent
        dp[0][0]=0; dp[1][0]=1;
        dp[0][1]=1; dp[1][1]=1;
        for (int i=2;i<=n;++i){
            dp[i][0] = (dp[i-1][1] + dp[i-2][1]) % MOD;
            dp[i][1] = (dp[i-1][0] + dp[i-1][1]) % MOD;
        }
        long long res=dp[n][0]+dp[n][1];
        
        // Absent at different position
        for (int i=0;i<n;++i){
            res = (res + (dp[i][0]+dp[i][1]) * (dp[n-1-i][0]+dp[n-1-i][1])) % MOD;
        }
        return res;
    }
};

时间复杂度 O(n)

空间复杂度 O(n)

 

Reference
https://www.cnblogs.com/seyjs/p/10420247.html

标签:Attendance,包含,前面,int,最后,II,Record,vector,dp
来源: https://www.cnblogs.com/hankunyan/p/11463106.html