Leetcode 552. 学生出勤记录 II C++

本文深入解析LeetCode题目552学生出勤记录II,通过动态规划方法求解长度为n的所有可视为可奖励的出勤记录数量。文章详细阐述了解题思路与代码实现,帮助读者理解并掌握动态规划的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Leetcode 552. 学生出勤记录 II

题目

给定一个正整数 n,返回长度为 n 的所有可被视为可奖励的出勤记录的数量。 答案可能非常大,你只需返回结果mod 109 + 7的值。

学生出勤记录是只包含以下三个字符的字符串:

  1. ‘A’ : Absent,缺勤
  2. ‘L’ : Late,迟到
  3. ‘P’ : Present,到场

如果记录不包含多于一个’A’(缺勤)或超过两个连续的’L’(迟到),则该记录被视为可奖励的。

示例:

输入: n = 2
输出: 8 
解释:
有8个长度为2的记录将被视为可奖励:
"PP" , "AP", "PA", "LP", "PL", "AL", "LA", "LL"
只有"AA"不会被视为可奖励,因为缺勤次数超过一次。

**注意:**n 的值不会超过100000。

题解

动态规划
我们先不考虑有A这种情况,那么dp[n]表示长度为n的可奖励出勤记录

  • 假设最后一个记录为P,则只需要保证前几天为可奖励情况,即dp[n-1]
  • 假设最后一个记录为L,则 ···L 可以再分为4中情况···LLL、···PLL、···LPL、···PPL,符号奖励记录的也就是dp[n-1]-dp[n-4],即减去···LLL这种情况

故dp[n] = 2*dp[n-1]-dp[n-4]
现在加上A,则A可以出现在1~n的任意一天,如果是第i天缺席,则i-1天要满足奖励情况;后面的n-i天也需要满足奖励情况,也就是说dp[i-1] * dp[n-i]
由上面的转移方程可知,转移方程适用于n>=4的情况,因此我们需要对0~3进行初始化。详细过程见代码

代码

	int checkRecord(int n) {
        long mod = pow(10,9)+7;
        vector<int> dp(n>3 ? n+1 : 5,0);
        dp[0] = 1;
        dp[1] = 2;
        dp[2] = 4;
        dp[3] = 7;
        for(int i=4; i<=n; i++){
            dp[i] = ((2*dp[i-1])%mod + (mod-dp[i-4]))%mod;
        }
        long sum = dp[n];
        for (int i = 1; i <= n; i++) {
            sum += ((long)dp[i-1] * dp[n-i])%mod;
            sum %= mod;
        }
        return sum;
    } 

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/student-attendance-record-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值