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:
'A'
) for strictly fewer than 2 days total.'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
This problem asks to find the number of possible attendance records of length n
that satisfy two conditions:
The most efficient approach is using dynamic programming. We can represent the state of the attendance record using a 3-dimensional array:
dp[i][j][k]
represents the number of attendance records of length i
where:
j
indicates the number of absences (0 or 1).k
represents the number of consecutive late days (0, 1, or 2).Base Cases:
For i = 0
, we have:
dp[0][0][0] = 1
(empty string)Recurrence Relation:
For i > 0
, we can transition from the previous state (i-1
) based on the character added:
'P' (Present): We can add 'P' to any previous state without changing the number of absences or consecutive late days. Thus:
dp[i][j][0] += dp[i-1][j][k]
(for all k
)
'L' (Late): Adding 'L' increases the consecutive late days by 1. If k < 2
, we can add 'L':
dp[i][j][k+1] += dp[i-1][j][k]
'A' (Absent): Adding 'A' only if j < 1
(less than 2 absences):
dp[i][j+1][0] += dp[i-1][j][k]
(for all k
)
We update the dp
array iteratively, taking the modulo 10^9 + 7
to prevent integer overflow. The final answer is the sum of all possible states in dp[n-1]
.
n
days. The nested loops within the dynamic programming approach are constant time, O(1).dp
array is proportional to n
.Python3:
class Solution:
def checkRecord(self, n: int) -> int:
mod = 10**9 + 7
dp = [[[0, 0, 0], [0, 0, 0]] for _ in range(n)] # Initialize 3D DP array
# Base case: length 0 has one valid record (empty string)
dp[0][0][0] = 1
for i in range(1, n): # Iterate through lengths
#Adding 'P'
dp[i][0][0] = (dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2]) % mod
dp[i][1][0] = (dp[i - 1][1][0] + dp[i - 1][1][1] + dp[i - 1][1][2]) % mod
# Adding 'L'
dp[i][0][1] = dp[i - 1][0][0] # Only if there were no consecutive 'L' before
dp[i][0][2] = dp[i - 1][0][1] # Only if there were 1 consecutive 'L' before
dp[i][1][1] = dp[i-1][1][0]
dp[i][1][2] = dp[i-1][1][1]
#Adding 'A' (only if fewer than 2 'A's)
dp[i][1][0] = (dp[i][1][0] + dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2]) % mod
ans = 0
for j in range(2):
for k in range(3):
ans = (ans + dp[n - 1][j][k]) % mod
return ans
The other languages (Java, C++, Go) follow a very similar structure, maintaining the 3D dp
array and implementing the same recurrence relations. The key differences are primarily in syntax and data type handling. The core logic remains identical for optimal efficiency.