题目:学生出勤记录 II
可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:
‘A’:Absent,缺勤
‘L’:Late,迟到
‘P’:Present,到场
如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:
按 总出勤 计,学生缺勤(’A’)严格 少于两天。
学生 不会 存在 连续 3 天或 连续 3 天以上的迟到(’L’)记录。
给你一个整数 n ,表示出勤记录的长度(次数)。请你返回记录长度为 n 时,可能获得出勤奖励的记录情况 数量 。答案可能很大,所以返回对 109 + 7 取余 的结果。
示例 1:
1 | 输入:n = 2 |
示例 2:
1 | 输入:n = 1 |
示例 3:
1 | 输入:n = 10101 |
提示:
1 <= n <= 105
分析:
动态规划做多了,一来就想到动态规划,都忘了还能模拟遍历(不过以我击败5%的结果用暴力法必定超时)
考虑最简单的dp
数组dp[i]
表示有i天时可获得奖励的天数,0 <= i <= n
。但是还需要记录有i天时的缺勤天数和结尾连续迟到天数,为什么是结尾连续迟到天数呢,因为一旦连续迟到天数达到3天,就将dp
置0。所以要将dp
数组升维再升维变成dp[i][j][k]
dp[i][j][k]
表示 “有i天、缺勤j天、结尾连续迟到k天” 的可获得奖励天数
边界:dp[0][0][0] = 1
即还没开始上课,这时可以获得出勤奖励
状态转移分为三种情况:到场、迟到、缺勤
到场:今天上课到场,于是迟到天数清零,缺勤保持不变,将前一天不同j和不同k的dp
加起来
迟到:今天上课迟到,前一天的迟到天数只能在0和1之间,因为一旦前一天的结尾迟到天数到达2,今天再迟到就没有奖励了,dp
置零(置零不用特别计算,新建的未初始化数组就是0,不影响后续计算调用),于是迟到天数加一,缺勤保持不变,将前一天不同j和k - 1的dp
加起来
缺勤:今天上课缺勤,前一天的缺勤天数只能是0,理由同上,于是迟到天数清零,缺勤天数加一,将前一天j = 0和不同k的dp
加起来
题解:
1 | class Solution { |
结语:
动态规划解题思路的一次更新,对于dp
数组升维这件事一直都把握不住,这道题目的条件让人容易找到升维切入点,真是受益良多