学生出勤记录 II -- LeetCode -- 8.18
学生出勤记录
(记忆化DFS 或者 动态规划)
可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:
'A':Absent,缺勤'L':Late,迟到'P':Present,到场
如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:
- 按 总出勤 计,学生缺勤(
'A')严格 少于两天。 - 学生 不会 存在 连续 3 天或 连续 3 天以上的迟到(
'L')记录。
给你一个整数 n ,表示出勤记录的长度(次数)。请你返回记录长度为 n 时,可能获得出勤奖励的记录情况 数量 。答案可能很大,所以返回对 10^9 + 7 取余 的结果。
示例 1:
输入:n = 2 输出:8 解释: 有 8 种长度为 2 的记录将被视为可奖励: "PP" , "AP", "PA", "LP", "PL", "AL", "LA", "LL" 只有"AA"不会被视为可奖励,因为缺勤次数为 2 次(需要少于 2 次)。
DFS:
class Solution {
public:
int mod = 1000000007;
//int mod = 10e9 + 7;
int a[100005][2][3];
int dfs(int u, int acnt, int lcnt){
if(acnt >= 2 || lcnt >= 3)return 0;
if(u == 0)return 1;
if(a[u][acnt][lcnt] != -1)return a[u][acnt][lcnt];
int ans = 0;
ans = dfs(u - 1, acnt + 1, 0) % mod;
ans = (ans + dfs(u - 1, acnt, lcnt + 1)) % mod;
ans = (ans + dfs(u - 1, acnt, 0)) % mod;
a[u][acnt][lcnt] = ans;//用于记忆
return ans;
}
int checkRecord(int n) {
for(int i = 0; i <= n; i++){
for(int j = 0; j < 2; j++){
for(int k = 0; k < 3; k++){
a[i][j][k] = -1;
}
}
}
return dfs(n, 0, 0);
}
};
速度一般。
动态规划:
基本上可以说这是通过记忆化的DFS演变过来的。
比如说a[i][0][0] = a[i - 1][0][0] + a[i - 1][0][1] + a[i - 1][0][2];
解:当第 i 天时,还不存在旷课和迟到情况的条件下,只能由一下三种情况推演而来
①当 i - 1天的时候,没有旷课和迟到;a[i - 1][0][0];
②当 i - 1天的时候,没有旷课和一次迟到;a[i - 1][0][1];//这时,咱在第 i 天的时候加上 P(到场) 的话,迟到次数则会情况变为 0;
③当 i - 1天的时候,没有旷课和两次迟到;a[i - 1][0][2];//同理
class Solution {
public:
int mod = 1000000007;
long long a[100005][2][3];
int checkRecord(int n) {
a[0][1][0] = 1;
a[0][0][0] = 1;
a[0][0][1] = 1;
for(int i = 1; i < n; i++) {
//加入 P
a[i][0][0] = (a[i - 1][0][0] + a[i - 1][0][1] + a[i - 1][0][2]) % mod;
a[i][1][0] = (a[i - 1][1][0] + a[i - 1][1][1] + a[i - 1][1][2]) % mod;
//加入 A
a[i][1][0] = (a[i][1][0] + a[i - 1][0][0] + a[i - 1][0][1] + a[i - 1][0][2]) % mod;//这个可以和上面那个合并
//加入 L
a[i][0][1] = a[i - 1][0][0] % mod;
a[i][0][2] = a[i - 1][0][1] % mod;
a[i][1][1] = a[i - 1][1][0] % mod;
a[i][1][2] = a[i - 1][1][1] % mod;
}
long long ans = 0;
for(int i = 0; i <= 1; i++){
for(int j = 0; j <= 2; j++){
ans = (ans + a[n - 1][i][j]) % mod;
}
}
cout << ans << endl;
return ans;
}
};
比记忆化DFS快上不少。

浙公网安备 33010602011771号