LeetCode每日一题(552. Student Attendance Record II)

An attendance record for a student can be represented as a string where each character signifies whether the student was absent, late, or present on that day. The record only contains the following three characters:

‘A’: Absent.
‘L’: Late.
‘P’: Present.
Any student is eligible for an attendance award if they meet both of the following criteria:

The student was absent (‘A’) for strictly fewer than 2 days total.
The student was never late (‘L’) for 3 or more consecutive days.
Given an integer n, return the number of possible attendance records of length n that make a student eligible for an attendance award. The answer may be very large, so return it modulo 109 + 7.

Example 1:

Input: n = 2
Output: 8

Explanation: There are 8 records with length 2 that are eligible for an award:
“PP”, “AP”, “PA”, “LP”, “PL”, “AL”, “LA”, “LL”
Only “AA” is not eligible because there are 2 absences (there need to be fewer than 2).

Example 2:

Input: n = 1
Output: 3

Example 3:

Input: n = 10101
Output: 183236316

Constraints:

  • 1 <= n <= 105

l[i]代表第 i 天为 L 时,可以拿奖的组合数量
p[i]代表第 i 天为 P 时,可以拿奖的组合数量
a[i]代表第 i 天为 A 时,可以拿奖的组合数量

第 i 天为 L 时, 我们要想拿奖,需要保证(i-1)和(i-2)两天不能都为 L, 否则就会形成连续三天迟到不能拿奖的情况。反过来想, 只要(i-1)和(i-2)两天中的任意一天为 P 或者 A, 我们就可以继续拿奖。所以 l[i] = (i-1)为 P 的拿奖组合 + (i-1)为 A 的拿奖组合 + (i-2)为 P 的拿奖组合 + (i-2)为 A 的拿奖组合, 即 l[i] = p[i-1] + a[i-1] + p[i-2] + a[i-2]

第 i 天为 P 时, 只要 i-1 天的状态可以拿奖,我们就可以拿奖。所以, p[i] = l[i-1] + p[i-1] + a[i-1]

第 i 天为 A 时, 只要 i 之前的天里没有 A 即可以拿奖。但是现在我们想表达之前的天数里没有 A 比较困难, 所以我们要定义另外两个表达方式:
nal[i]代表第 i 天为 L 且前面所有的天数中都不存在 A 的,可以拿奖的组合数量
nap[i]代表第 i 天为 p 且前面所有的天数中都不存在 A 的,可以拿奖的组合数量
这样 a[i]就可以表达为 nal[i-1] + nap[i-1]

nap[i] = nap[i-1] + nal[i-1], 这个比较好理解

nal[i]跟我们前面分析的 l[i]相似, 只要 i-1 和 i-2 有一天不为 L 且不为 A 即可, 既不为 L 也不为 A 那就只剩下 P 了, 所以 nal[i] = nap[i-1] + nap[i-2]

最终答案是(l[n-1] + p[n-1] + a[n-1]) % 1000000007, 这也比较好理解, 分别以 L、P、A 结尾的获奖组合数的和




impl Solution {
    pub fn check_record(n: i32) -> i32 {
        if n == 1 {
            return 3;
        }
        const M: i64 = 10i64.pow(9) + 7;
        let mut a = vec![0; n as usize];
        let mut l = vec![0; n as usize];
        let mut p = vec![0; n as usize];
        let mut nal = vec![0; n as usize];
        let mut nap = vec![0; n as usize];
        a[0] = 1;
        a[1] = 2;
        l[0] = 1;
        l[1] = 3;
        p[0] = 1;
        p[1] = 3;
        nal[0] = 1;
        nal[1] = 2;
        nap[0] = 1;
        nap[1] = 2;
        for i in 2..n as usize {
            nap[i] = (nal[i - 1] + nap[i - 1]) % M;
            nal[i] = (nap[i - 1] + nap[i - 2]) % M;
            a[i] = (nap[i - 1] + nal[i - 1]) % M;
            l[i] = (a[i - 1] + p[i - 1] + a[i - 2] + p[i - 2]) % M;
            p[i] = (a[i - 1] + l[i - 1] + p[i - 1]) % M;
        }
        ((a[n as usize - 1] + l[n as usize - 1] + p[n as usize - 1]) % M) as i32
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值