Problem
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:
1 | Input: n = 2 |
Example 2:
1 | Input: n = 1 |
Example 3:
1 | Input: n = 10101 |
Constraints:
1 <= n <= 105
Analysis
这道题目是系列题,第一个题目太简单了就不写题解了,主要就是给出一个字符串序列,要求判断是不是eligible for an attendance award。还是这道题目比较有意思,题目的规则和第一题一样,不同在于它是给出了一个n
,问有多少种不同的组合。我们一看答案要取模,下意识就是dp了。状态很简单,就是n
个状态。
定义三个dp数组,分别是以A结尾,以L结尾和以P结尾,那么答案就是三个的和。我们先来看转移方程。
- 对
P[i]
来说,因为没有什么限制,所以P[i] = P[i - 1] + A[i - 1] + L[i - 1]
; - 对
L[i]
来说,分成两部分,第一部分是当i - 1
是L
的话,因为不能连续三个L,所以i - 2
是P或者A,应该是P[i - 2] + A[i - 2]
;第二部分是当i - 1
是A或P的话,直接就是P[i - 1] + A[i - 1]
,所以整体就是L[i] = P[i - 1] + A[i - 1] + P[i - 2] + A[i - 2]
; - 对
A[i]
来说是最难的,因为我们要之前之前出现过几次A,如果当前是以A结尾,说明之前是不能出现A的,我们先定义P1[i]
为前i个以P结尾但不包含A的数量;定义L1[i]
为前i个以L结尾但不包含L的数量,这两个的转移方程很好计算,可以参考上面两个的计算,P1[i] = P1[i - 1] + L1[i - 1]
,L1[i] = P1[i - 1] + P1[i - 2]
,然后A[i] = P1[i - 1] + L1[i - 1]
,代入上面两个式子化简得到A[i] = A[i - 1] + A[i - 2] + A[i - 3]
。
至此,状态转移方程就写完了,可以直接写代码了。
Solution
这里的base case需要额外处理,三个dp数组的base case不一样,我们只需要考虑遍历的时候下标什么时候不合法,把这些case处理就可以了。
Code
1 | class Solution { |
Summary
这道题目是dp中算比较困难的,主要难点在于A[i]
的化简。这道题目的分享到这里,感谢你的支持!