Welcome to Subscribe On Youtube
552. Student Attendance Record II
Description
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
Solutions
Solution 1: Depth-First Search + Memoization
We design a function $dfs(i, j, k)$, which represents the number of attendance rewards that can be obtained when the current number of absences is $j$ and the last number of consecutive late arrivals is $k$ starting from the $i$ attendance record. Then the answer is $dfs(0, 0, 0)$.
The execution process of function $dfs(i, j, k)$ is as follows:
- If $i \ge n$, it means that all attendance records have been traversed and $1$ is returned;
- If $j = 0$, it means that the current number of absences is $0$, then you can choose to be absent, that is, $dfs(i + 1, j + 1, 0)$;
- If $k \lt 2$, it means that the current number of consecutive late arrivals is less than $2$, then you can choose to be late, that is, $dfs(i + 1, j, k + 1)$;
- In any case, there is an option to be present, which is $dfs(i + 1, j, 0)$.
We add the results of the above three cases, which is the result of $dfs(i, j, k)$.
To avoid double calculations, we can use memoized search.
Time complexity $O(n)$, space complexity $O(n)$. Where $n$ is the length of the attendance record.
Solution 2
Dynamic programming, define dp[i][j][k] to represent the number of attendance rewards that can be obtained when absent j times and k consecutive latenesses in the previous i days
Status transfer requires separate discussion of attendance on day i:
- Absence: There cannot be any previous absence record, i.e.
j == 0 - Late: Late at most 1 time in a row, i.e.
k == 0 || k == 1 - Attendance: unlimited
-
class Solution { private static final int MOD = 1000000007; public int checkRecord(int n) { long[][][] dp = new long[n][2][3]; // base case dp[0][0][0] = 1; dp[0][0][1] = 1; dp[0][1][0] = 1; for (int i = 1; i < n; i++) { // A dp[i][1][0] = (dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2]) % MOD; // L dp[i][0][1] = dp[i - 1][0][0]; dp[i][0][2] = dp[i - 1][0][1]; dp[i][1][1] = dp[i - 1][1][0]; dp[i][1][2] = dp[i - 1][1][1]; // 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][0] + dp[i - 1][1][0] + dp[i - 1][1][1] + dp[i - 1][1][2]) % MOD; } long ans = 0; for (int j = 0; j < 2; j++) { for (int k = 0; k < 3; k++) { ans = (ans + dp[n - 1][j][k]) % MOD; } } return (int) ans; } } // Solution 2 class Solution { private static final int MOD = 1000000007; public int checkRecord(int n) { long[][][] dp = new long[n][2][3]; // base case dp[0][0][0] = 1; dp[0][0][1] = 1; dp[0][1][0] = 1; for (int i = 1; i < n; i++) { // A dp[i][1][0] = (dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2]) % MOD; // L dp[i][0][1] = dp[i - 1][0][0]; dp[i][0][2] = dp[i - 1][0][1]; dp[i][1][1] = dp[i - 1][1][0]; dp[i][1][2] = dp[i - 1][1][1]; // 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][0] + dp[i - 1][1][0] + dp[i - 1][1][1] + dp[i - 1][1][2]) % MOD; } long ans = 0; for (int j = 0; j < 2; j++) { for (int k = 0; k < 3; k++) { ans = (ans + dp[n - 1][j][k]) % MOD; } } return (int) ans; } } -
constexpr int MOD = 1e9 + 7; class Solution { public: int checkRecord(int n) { using ll = long long; vector<vector<vector<ll>>> dp(n, vector<vector<ll>>(2, vector<ll>(3))); // base case dp[0][0][0] = dp[0][0][1] = dp[0][1][0] = 1; for (int i = 1; i < n; ++i) { // A dp[i][1][0] = (dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2]) % MOD; // L dp[i][0][1] = dp[i - 1][0][0]; dp[i][0][2] = dp[i - 1][0][1]; dp[i][1][1] = dp[i - 1][1][0]; dp[i][1][2] = dp[i - 1][1][1]; // 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][0] + dp[i - 1][1][0] + dp[i - 1][1][1] + dp[i - 1][1][2]) % MOD; } ll ans = 0; for (int j = 0; j < 2; ++j) { for (int k = 0; k < 3; ++k) { ans = (ans + dp[n - 1][j][k]) % MOD; } } return ans; } }; // Solution 2 constexpr int MOD = 1e9 + 7; class Solution { public: int checkRecord(int n) { using ll = long long; vector<vector<vector<ll>>> dp(n, vector<vector<ll>>(2, vector<ll>(3))); // base case dp[0][0][0] = dp[0][0][1] = dp[0][1][0] = 1; for (int i = 1; i < n; ++i) { // A dp[i][1][0] = (dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2]) % MOD; // L dp[i][0][1] = dp[i - 1][0][0]; dp[i][0][2] = dp[i - 1][0][1]; dp[i][1][1] = dp[i - 1][1][0]; dp[i][1][2] = dp[i - 1][1][1]; // 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][0] + dp[i - 1][1][0] + dp[i - 1][1][1] + dp[i - 1][1][2]) % MOD; } ll ans = 0; for (int j = 0; j < 2; ++j) { for (int k = 0; k < 3; ++k) { ans = (ans + dp[n - 1][j][k]) % MOD; } } return ans; } }; -
class Solution: def checkRecord(self, n: int) -> int: mod = int(1e9 + 7) dp = [[[0, 0, 0], [0, 0, 0]] for _ in range(n)] # base case dp[0][0][0] = dp[0][0][1] = dp[0][1][0] = 1 for i in range(1, n): # A dp[i][1][0] = (dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2]) % mod # L dp[i][0][1] = dp[i - 1][0][0] dp[i][0][2] = dp[i - 1][0][1] dp[i][1][1] = dp[i - 1][1][0] dp[i][1][2] = dp[i - 1][1][1] # 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][0] + dp[i - 1][1][0] + dp[i - 1][1][1] + dp[i - 1][1][2] ) % mod ans = 0 for j in range(2): for k in range(3): ans = (ans + dp[n - 1][j][k]) % mod return ans # Solution 2 class Solution: def checkRecord(self, n: int) -> int: mod = int(1e9 + 7) dp = [[[0, 0, 0], [0, 0, 0]] for _ in range(n)] # base case dp[0][0][0] = dp[0][0][1] = dp[0][1][0] = 1 for i in range(1, n): # A dp[i][1][0] = (dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2]) % mod # L dp[i][0][1] = dp[i - 1][0][0] dp[i][0][2] = dp[i - 1][0][1] dp[i][1][1] = dp[i - 1][1][0] dp[i][1][2] = dp[i - 1][1][1] # 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][0] + dp[i - 1][1][0] + dp[i - 1][1][1] + dp[i - 1][1][2] ) % mod ans = 0 for j in range(2): for k in range(3): ans = (ans + dp[n - 1][j][k]) % mod return ans -
const _mod int = 1e9 + 7 func checkRecord(n int) int { dp := make([][][]int, n) for i := 0; i < n; i++ { dp[i] = make([][]int, 2) for j := 0; j < 2; j++ { dp[i][j] = make([]int, 3) } } // base case dp[0][0][0] = 1 dp[0][0][1] = 1 dp[0][1][0] = 1 for i := 1; i < n; i++ { // A dp[i][1][0] = (dp[i-1][0][0] + dp[i-1][0][1] + dp[i-1][0][2]) % _mod // L dp[i][0][1] = dp[i-1][0][0] dp[i][0][2] = dp[i-1][0][1] dp[i][1][1] = dp[i-1][1][0] dp[i][1][2] = dp[i-1][1][1] // 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][0] + dp[i-1][1][0] + dp[i-1][1][1] + dp[i-1][1][2]) % _mod } var ans int for j := 0; j < 2; j++ { for k := 0; k < 3; k++ { ans = (ans + dp[n-1][j][k]) % _mod } } return ans } // Solution 2 const _mod int = 1e9 + 7 func checkRecord(n int) int { dp := make([][][]int, n) for i := 0; i < n; i++ { dp[i] = make([][]int, 2) for j := 0; j < 2; j++ { dp[i][j] = make([]int, 3) } } // base case dp[0][0][0] = 1 dp[0][0][1] = 1 dp[0][1][0] = 1 for i := 1; i < n; i++ { // A dp[i][1][0] = (dp[i-1][0][0] + dp[i-1][0][1] + dp[i-1][0][2]) % _mod // L dp[i][0][1] = dp[i-1][0][0] dp[i][0][2] = dp[i-1][0][1] dp[i][1][1] = dp[i-1][1][0] dp[i][1][2] = dp[i-1][1][1] // 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][0] + dp[i-1][1][0] + dp[i-1][1][1] + dp[i-1][1][2]) % _mod } var ans int for j := 0; j < 2; j++ { for k := 0; k < 3; k++ { ans = (ans + dp[n-1][j][k]) % _mod } } return ans }