552. Student Attendance Record II

552. Student Attendance Record II
Given a positive integer n, return the number of all possible attendance records with length n, which will be regarded as rewardable. The answer may be very large, return it after mod 109 + 7.
A student attendance record is a string that only contains the following three characters:
‘A’ : Absent.
‘L’ : Late.
‘P’ : Present.
A record is regarded as rewardable if it doesn’t contain more than one ‘A’ (absent) or more than two continuous ‘L’ (late).
Example 1:
Input: n = 2
Output: 8
Explanation:
There are 8 records with length 2 will be regarded as rewardable:
“PP” , “AP”, “PA”, “LP”, “PL”, “AL”, “LA”, “LL”
Only “AA” won’t be regarded as rewardable owing to more than one absent times.
Note: The value of n won’t exceed 100,000.
提示:提交代码后,需要用简洁的语言解释一下代码思路~ 谢谢
https://leetcode.com/problems/student-attendance-record-ii/description/ 
/* 552. Student-Attendance-Recod-II
此题明显要用DP,但是如何设计状态和状态转移方程都非常南翔。但最终的解决其实也非常巧妙,原来用到了
多元状态的转移。任何一种序列,可以归纳为六种状态,a[0][0],a[0][1],a[0][2],a[1][0],a[1][1],a[1][2],
状态ai|j的定义是:其中i表示这个数列立absence出现的次数,显然对于一个avlid的数列,i的范围只能是0和1;
j表示这个数列里末尾连续出现late的次数,显然对于一个valid的数列,j的范围只能是0,1,2.我们发现,随着
record长度增加,序列的状态就是在这六种状态之间转移,规律如下:
新状态   旧状态
a0|2  =  a0|1
a0|1  =  a0|0
a0|0  =  a0|0 + a0|1 + a0|2
a1|2  =  a1|1
a1|1  =  a1|0
a1|0  =  a1|0 + a1|2 + a0|0 + a0|1 + a0|2
这样的动态规划不需要dp数组,只要几个变量记录当前状态即可,随着长度的增加,这些新状态根据之前的旧状
态就能更新。需要用临时变量把所有的旧状态保存下来,再来更新状态。
类似的DP题目还有:
714.Best-Time-to-Buy-and-Sell-Stock-with-Transaction-Free
487.Max Consecutive One II
376.Wiggle Subsequence
*/

class Solution{
public:
        int checkRecord(int n)
        {
                long long a0|0=1,a0|1=1,a0|2=0,a1|0=1,a1|1=0,a1|2=0;
                long long M=1e9+7;
                for(int i=1; i<n; i++)
                {
                        long long a0|0_temp = a0|0;
                        long long a0|1_temp = a0|1;
                        long long a0|2_temp = a0|2;
                        long long a1|0_temp = a1|0;
                        long long a1|1_temp = a1|1;
                        long long a1|2_temp = a1|2;
                        a0|0 = (a0|0_temp + a0|1_temp + a0|2_temp)%M;
                        a0|1 = a0|0_temp;
                        a0|2 = a0|1_temp;
                        a1|0 = a1|0_temp + a1|2_temp + a0|0_temp + a0|1_temp + a0|2_temp;
                        a1|1 = a1|0_temp;
                        a1|2 = a1|1_temp;
                }
                return (a0|0 + a0|1 + a0|2 + a1|0 + a1|1 + a1|2);
        }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值