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:

  1. 'A' : Absent.
  2. 'L' : Late.
  3. '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.

题目描述:每天有三种出勤情况:A:出席;L:迟到;P:旷课;连续迟到两天以上(不含),或者旷课一次以上(不含)记为无奖励。问连续n天的出勤状况,有多少种有奖励的组合。

结题思路:动态规划,记录连续i天的有奖励组合数目,递推数连续i+1天的有奖励组合数目。根据有奖励的限制,我们应当把连续i天的有奖励组合进行分类,根据第一条限制,连续迟到不能超过两天,我们可以将出勤情况分为3类,因为要求连续迟到,因此我们只关心组合末尾的连续迟到天数,既然有奖励(连续迟到不超过两天),那么连续迟到天数就只能是0,1和2;根据第二条限制,旷课不超过一次,我们可以分为两类,一类是此前没有旷课过,和此前旷课一次;将两种分类综合起来,我们可以吧连续i天的有奖励出勤组合分为6类:

dp[i][0]:此前未旷课,且最后一天未迟到

dp[i][1]:此前未旷课,且最后一天迟到

dp[i][2]:此前未旷课,且最后两天迟到

dp[i][3]:此前旷课一次,且最后一天未迟到

dp[i][4]:此前旷课一次,且最后一天迟到

dp[i][5]:此前旷课一次,且最后两天迟到

接下来我们想一想递推公式,用dp[i][0]A表示前i天未旷课,且第i天没有迟到,且第i+1天出席,类似的,用dp[i][1]L表示前i天没有旷课,且第i天迟到,且第i+1天迟到,我们可以把递推公式总结如下:

dp[i+1][0] = dp[i][0]P + dp[i][1]P + dp[i][2]P + dp[i][3]A + dp[i][4]A + dp[i][5]A

dp[i+1][1] = dp[i][0]L

dp[i+1][2] = dp[i][1]L

dp[i+1][3] = dp[i][3]P + dp[i][4]P + dp[i][5]P

dp[i+1][4] = dp[i][3]L

dp[i+1][5] = dp[i][4]L

然后我们发现,实际上只需要记录两天的出勤数目,即前一天和今天,然后迭代计算,综上,代码如下:

    public int checkRecord(int n) {
        long[] cur = new long[]{1, 0, 0, 1, 1, 0}, next;
        if(n == 0)
        	return 0;
        for(int i = 1; i < n; i++){
        	next = new long[6];
        	next[0] = cur[0] + cur[1] + cur[2] + cur[3] + cur[4] + cur[5];
        	next[1] = cur[0];
        	next[2] = cur[1];
        	next[3] = cur[3] + cur[4] + cur[5];
        	next[4] = cur[3];
        	next[5] = cur[4];
        	for(int j = 0; j < 6; j++)
        		next[j] %= 1000000007;
        	cur = next;
        }
        long res = 0;
        for(long num : cur)
        	res += num;
        res %= 1000000007;
        return (int)res;
    }

阅读更多
文章标签: LeetCode
个人分类: LeetCode
上一篇K-th Symbol in Grammar
下一篇Minimum Swaps To Make Sequences Increasing
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭