学生出勤记录 II
难度:
标签:
题目描述
代码结果
运行时间: 126 ms, 内存: 16.0 MB
/*
* 思路:
* - 使用流式处理来计算合法出勤记录的数量。
* - 我们使用一个包含所有可能的长度为 n 的出勤记录的流。
* - 然后过滤出满足条件的记录:
* - 缺勤次数小于 2
* - 不存在连续 3 天或以上的迟到记录
* - 最后统计符合条件的记录数量,并取模 (10^9 + 7)。
*/
import java.util.stream.Stream;
public class AttendanceRewardStream {
private static final int MOD = 1000000007;
public int checkRecord(int n) {
return (int) Stream.generate(() -> new char[n])
.limit((int) Math.pow(3, n))
.parallel()
.map(this::generateRecord)
.filter(this::isValid)
.count() % MOD;
}
private String generateRecord(char[] chars) {
int index = 0;
for (int i = 0; i < chars.length; i++) {
if (index % 3 == 0) chars[i] = 'P';
else if (index % 3 == 1) chars[i] = 'L';
else chars[i] = 'A';
index++;
}
return new String(chars);
}
private boolean isValid(String record) {
int absentCount = 0;
int lateStreak = 0;
for (char c : record.toCharArray()) {
if (c == 'A') absentCount++;
if (c == 'L') lateStreak++;
else lateStreak = 0;
if (absentCount >= 2 || lateStreak >= 3) return false;
}
return true;
}
}
解释
方法:
这个题解使用了矩阵快速幂的方法来解决问题。它定义了一个6个状态的转移矩阵,其中每个状态表示当前的出勤记录状态。通过对转移矩阵进行快速幂运算,可以得到从初始状态经过 n-1 次转移后的各个状态的数量。最后将所有状态的数量相加即可得到答案。为了避免大数问题,过程中的计算都对 10^9+7 取模。
时间复杂度:
O(logn)
空间复杂度:
O(1)
代码细节讲解
🦆
题解中提到的六个状态具体代表什么意义,能否具体解释每个状态所对应的出勤记录类型?
▷🦆
在定义的状态转移矩阵中,矩阵的每个元素具体如何表示状态之间的转移?例如,base[0][1] 和 base[3][4] 分别代表什么意义?
▷🦆
矩阵快速幂在这个问题中的应用是如何确保能够有效计算出 n 天的可能状态数量的?
▷🦆
题解中初始化矩阵 init 的设置是怎样确定的?每个元素的初始值代表什么?
▷相关问题
学生出勤记录 I
给你一个字符串 s
表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:
'A'
:Absent,缺勤'L'
:Late,迟到'P'
:Present,到场
如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:
- 按 总出勤 计,学生缺勤(
'A'
)严格 少于两天。 - 学生 不会 存在 连续 3 天或 连续 3 天以上的迟到(
'L'
)记录。
如果学生可以获得出勤奖励,返回 true
;否则,返回 false
。
示例 1:
输入:s = "PPALLP" 输出:true 解释:学生缺勤次数少于 2 次,且不存在 3 天或以上的连续迟到记录。
示例 2:
输入:s = "PPALLL" 输出:false 解释:学生最后三天连续迟到,所以不满足出勤奖励的条件。
提示:
1 <= s.length <= 1000
s[i]
为'A'
、'L'
或'P'