非常简单,分别用两个变量记录"累计缺勤"和"连续迟到"的天数即可。
class Solution {
public boolean checkRecord(String s) {
int abstCnt = 0;
int lateCnt = 0;
for (char c : s.toCharArray()) {
abstCnt = abstCnt + (c == 'A' ? 1 : 0);
lateCnt = (c == 'L' ? lateCnt + 1 : 0);
if (abstCnt >= 2 || lateCnt >= 3) {
return false;
}
}
return true;
}
}
动态规划
dp[i][j][k]的含义为:"当前为第i天,且处于累计缺勤i次、连续缺勤j次的状态,能获得出勤奖励的组合数"
class Solution {
public int checkRecord(int n) {
// dp[i][j][k]的含义为:当前为第i天,且处于累计缺勤i次、连续缺勤j次的状态,能获得出勤奖励的组合数
long[][][] dp = new long[n + 1][2][3];
// 初始化
dp[1][0][0] = 1;
dp[1][0][1] = 1;
dp[1][0][2] = 0;
dp[1][1][0] = 1;
dp[1][1][1] = 0;
dp[1][1][2] = 0;
// 状态转移
for (int i = 2; i <= n; i++) {
dp[i][0][0] = (dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2]) % 1000000007;
dp[i][0][1] = (dp[i - 1][0][0]) % 1000000007;
dp[i][0][2] = (dp[i - 1][0][1]) % 1000000007;
dp[i][1][0] = (dp[i - 1][0][0] + dp[i - 1][0][1] + dp[i - 1][0][2] + dp[i - 1][1][0] + dp[i - 1][1][1] + dp[i - 1][1][2]) % 1000000007;
dp[i][1][1] = (dp[i - 1][1][0]) % 1000000007;
dp[i][1][2] = (dp[i - 1][1][1]) % 1000000007;
}
return (int) ((dp[n][0][0] + dp[n][0][1] + dp[n][0][2] + dp[n][1][0] + dp[n][1][1] + dp[n][1][2]) % 1000000007);
}
}
题目不好理解,建议多读几遍。
本题使用了"前缀和"+"二分查找"的技巧,从而控制住了空间复杂度:
array = [1, 3, 1, 2]
preSum = [1, 4, 5, 7]
random取[1,7]的随机整数,在前缀和数组中二分搜索这个整数,取下标即可:
index0 —— 1
index1 —— 2、3、4
index2 —— 5
index3 —— 6、7
class Solution {
private int[] preSum;
public Solution(int[] w) {
preSum = new int[w.length];
preSum[0] = w[0];
for (int i = 1; i < w.length; i++) {
preSum[i] = preSum[i - 1] + w[i];
}
}
public int pickIndex() {
int n = (int) (Math.random() * preSum[preSum.length - 1] + 1);
return binarySearch(n);
}
private int binarySearch(int target) {
int left = 0;
int right = preSum.length - 1;
int mid;
while (left < right) {
mid = left + (right - left) / 2;
if (preSum[mid] < target) {
left = mid + 1;
} else {
right = mid;
}
}
return left;
}
}
检索标记:528. 按权重随机选择给定一个正整数数组 w ,其中 w[i] 代表下标 i 的权重(下标从 0 开始),请写一个函数 pickIndex ,它可以随机地获取下标 i,选取下标 i 的概率与 w[i] 成正比。例如,对于 w = [1, 3],挑选下标 0 的概率为 1 / (1 + 3) = 0.25 (即,25%),而选取下标 1 的概率为 3 / (1 + 3) = 0.75(即,75%)。也就是说,选取下标 i 的概率为 w[i] / sum(w) 。551. 学生出勤记录 I给你一个字符串 s 表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:‘A’:Absent,缺勤’L’:Late,迟到’P’:Present,到场如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:按 总出勤 计,学生缺勤(‘A’)严格 少于两天。学生 不会 存在 连续 3 天或 连续 3 天以上的迟到(‘L’)记录。如果学生可以获得出勤奖励,返回 true ;否则,返回 false 。552. 学生出勤记录 II可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:‘A’:Absent,缺勤’L’:Late,迟到’P’:Present,到场如果学生能够 同时 满足下面两个条件,则可以获得出勤奖励:按 总出勤 计,学生缺勤(‘A’)严格 少于两天。学生 不会 存在 连续 3 天或 连续 3 天以上的迟到(‘L’)记录。给你一个整数 n ,表示出勤记录的长度(次数)。请你返回记录长度为 n 时,可能获得出勤奖励的记录情况 数量 。答案可能很大,所以返回对 109 + 7 取余 的结果。