3134.找出唯一性数组的中位数

目标

给你一个整数数组 nums 。数组 nums 的 唯一性数组 是一个按元素从小到大排序的数组,包含了 nums 的所有 非空子数组中 不同元素的个数。

换句话说,这是由所有 0 <= i <= j < nums.length 的 distinct(nums[i..j]) 组成的递增数组。

其中,distinct(nums[i..j]) 表示从下标 i 到下标 j 的子数组中不同元素的数量。

返回 nums 唯一性数组 的 中位数 。

注意,数组的 中位数 定义为有序数组的中间元素。如果有两个中间元素,则取值较小的那个。

示例 1:

输入:nums = [1,2,3]
输出:1
解释:
nums 的唯一性数组为 [distinct(nums[0..0]), distinct(nums[1..1]), distinct(nums[2..2]), distinct(nums[0..1]), distinct(nums[1..2]), distinct(nums[0..2])],即 [1, 1, 1, 2, 2, 3] 。唯一性数组的中位数为 1 ,因此答案是 1 。

示例 2:

输入:nums = [3,4,3,4,5]
输出:2
解释:
nums 的唯一性数组为 [1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3] 。唯一性数组的中位数为 2 ,因此答案是 2 。

示例 3:

输入:nums = [4,3,5,4]
输出:2
解释:
nums 的唯一性数组为 [1, 1, 1, 1, 2, 2, 2, 3, 3, 3] 。唯一性数组的中位数为 2 ,因此答案是 2 。

说明:

  • 1 <= nums.length <= 10^5
  • 1 <= nums[i] <= 10^5

思路

定义数组的唯一性数组为其所有 子数组 中不同元素个数从小到大排序,求唯一性数组的中位数。

长度为 n 的子数组的个数为 n(n+1)/2,唯一性数组的中位数下标为 n(n+1)/4 - 1 是第 (n(n+1)/2 + 1)/2 个元素。

问题的关键在于,如何快速判断数组中不同元素的个数。我们想要这样一个hash表,可以根据 start end 动态调整其中的元素。

一般来说枚举子数组使用的是双层循环,外层枚举起点,内层从起点开始枚举终点直到结尾,当然也可以外层枚举终点,内层枚举0到终点作为起点,时间复杂度为 O(n^2)。这里的问题在于如何保存区间与对应不重复元素个数的对应关系,以及如何计算不重复元素个数。本来 O(n^2) 就会超时,如果针对每个区间再循环判断,就更不行了。这里其实可以模拟变长的滑动窗口,通过修改窗口中加入与移除元素在map中对应的计数,如果计数为0则删除,这样map里的元素个数即为当前窗口内不重复元素个数。但是并没有保存这个状态(区间对应的不同元素个数)。我们可以将 start, end 压缩到一个long型数字中,倒是也可以记录。假如我们有了这个对应关系,我们还需要将它排序然后取中位数。

看了题解使用的是二分+滑动窗口,确实比较绕,我也没有仔细想清楚,这里面有几个关键点:

  • 唯一性数组中元素的取值范围是 1 ~ n,元素递增的步长为1,如果某个子数组比之前的子数组多了2个不同的元素,那么总是可以去掉其中一个使得子数组仅多1个不同元素。
  • 思考 唯一性元素的个数 小于等于 m 的子数组有多少个?找到唯一性元素个数第一次覆盖 (n(n+1)/2 + 1)/2 的 m 就是要找的答案。
  • 假设我们已经知道 m 对应的 cnt,只需要找到第一个大于等于 (n(n+1)/2 + 1)/2 的cnt即可,可以使用二分查找。
  • 问题转化为 计算唯一性元素的个数 小于等于 m 的子数组个数。使用滑动窗口。

而这里需要计算的是子数组中不同元素的个数,

// todo

代码

性能

690.员工的重要性

目标

你有一个保存员工信息的数据结构,它包含了员工唯一的 id ,重要度和直系下属的 id 。

给定一个员工数组 employees,其中:

  • employees[i].id 是第 i 个员工的 ID。
  • employees[i].importance 是第 i 个员工的重要度。
  • employees[i].subordinates 是第 i 名员工的直接下属的 ID 列表。

给定一个整数 id 表示一个员工的 ID,返回这个员工和他所有下属的重要度的 总和。

示例 1:

输入:employees = [[1,5,[2,3]],[2,3,[]],[3,3,[]]], id = 1
输出:11
解释:员工 1 自身的重要度是 5 ,他有两个直系下属 2 和 3 ,而且 2 和 3 的重要度均为 3 。因此员工 1 的总重要度是 5 + 3 + 3 = 11 。

示例 2:

输入:employees = [[1,2,[5]],[5,-3,[]]], id = 5
输出:-3
解释:员工 5 的重要度为 -3 并且没有直接下属。因此,员工 5 的总重要度为 -3。

说明:

  • 1 <= employees.length <= 2000
  • 1 <= employees[i].id <= 2000
  • 所有的 employees[i].id 互不相同。
  • -100 <= employees[i].importance <= 100
  • 一名员工最多有一名直接领导,并可能有多名下属。
  • employees[i].subordinates 中的 ID 都有效。

思路

有一个数据结构 Employee,属性有 id、重要性、下属id集合。现在要查找给定id员工的重要性,即自身及下属的重要性之和。

直接使用map映射id与员工对象,使用dfs或者bfs搜索并累加重要性即可。

代码


/**
 * @date 2024-08-26 14:59
 */
public class GetImportance690 {
    class Employee {
        public int id;
        public int importance;
        public List<Integer> subordinates;
    }

    public int getImportance(List<Employee> employees, int id) {
        Employee root = null;
        Map<Integer, Employee> map = new HashMap<>();
        for (Employee employee : employees) {
            map.put(employee.id, employee);
        }
        int res = 0;
        Queue<Employee> q = new ArrayDeque<>(employees.size());
        q.offer(map.get(id));
        while (!q.isEmpty()) {
            int size = q.size();
            for (int i = 0; i < size; i++) {
                Employee node = q.poll();
                res += node.importance;
                for (Integer subordinate : node.subordinates) {
                    q.offer(map.get(subordinate));
                }
            }
        }
        return res;
    }
}

性能

698.划分为k个相等的子集

目标

给定一个整数数组 nums 和一个正整数 k,找出是否有可能把这个数组分成 k 个非空子集,其总和都相等。

示例 1:

输入: nums = [4, 3, 2, 3, 5, 2, 1], k = 4
输出: True
说明: 有可能将其分成 4 个子集(5),(1,4),(2,3),(2,3)等于总和。

示例 2:

输入: nums = [1,2,3,4], k = 3
输出: false

说明:

  • 1 <= k <= len(nums) <= 16
  • 0 < nums[i] < 10000
  • 每个元素的频率在 [1,4] 范围内

思路

给定一个数组 nums,判断能否将其划分为 k 个非空子集,要求每个子集的和都相等。

与数组中元素顺序无关可以排序。数组元素的和是可以枚举的,它一定大于等于数组中的最大元素。和确定了之后就可以从后向前判断能否组成这个和,如果不能则立即返回。

// todo

代码

性能

3146.两个字符串的排列差

目标

给你两个字符串 s 和 t,每个字符串中的字符都不重复,且 t 是 s 的一个排列。

排列差 定义为 s 和 t 中每个字符在两个字符串中位置的绝对差值之和。

返回 s 和 t 之间的 排列差 。

示例 1:

输入:s = "abc", t = "bac"
输出:2
解释:
对于 s = "abc" 和 t = "bac",排列差是:
"a" 在 s 中的位置与在 t 中的位置之差的绝对值。
"b" 在 s 中的位置与在 t 中的位置之差的绝对值。
"c" 在 s 中的位置与在 t 中的位置之差的绝对值。
即,s 和 t 的排列差等于 |0 - 1| + |2 - 2| + |1 - 0| = 2。

示例 2:

输入:s = "abcde", t = "edbac"
输出:12
解释: s 和 t 的排列差等于 |0 - 3| + |1 - 2| + |2 - 4| + |3 - 1| + |4 - 0| = 12。

说明:

  • 1 <= s.length <= 26
  • 每个字符在 s 中最多出现一次。
  • t 是 s 的一个排列。
  • s 仅由小写英文字母组成。

思路

有两个仅由小写英文字母组成的字符串,同一字符串中的字母各不相同,并且组成两个字符串所用的字母相同,只是排列可能不同。求这两个字符串中相同字母位置之差的绝对值之和。

使用长度为26的数组记录每个字母在字符串s中的位置,然后遍历字符串t,计算位置之差的绝对值并累加求和即可。

代码


/**
 * @date 2024-08-24 15:01
 */
public class FindPermutationDifference3146 {
    public int findPermutationDifference(String s, String t) {
        int res = 0;
        int[] pos = new int[26];
        int n = s.length();
        for (int i = 0; i < n; i++) {
            pos[s.charAt(i) - 'a'] = i;
        }
        for (int i = 0; i < n; i++) {
            res += Math.abs(pos[t.charAt(i) - 'a'] - i);
        }
        return res;
    }
}

性能

3145.大数组元素的乘积

目标

一个非负整数 x强数组 指的是满足元素为 2 的幂且元素总和为 x 的最短有序数组。下表说明了如何确定 强数组 的示例。可以证明,x 对应的强数组是独一无二的。

数字 二进制表示 强数组
1 00001 [1]
8 01000 [8]
10 01010 [2, 8]
13 01101 [1, 4, 8]
23 10111 [1, 2, 4, 16]

我们将每一个升序的正整数 i (即1,2,3等等)的 强数组 连接得到数组 big_numsbig_nums 开始部分为 [1, 2, 1, 2, 4, 1, 4, 2, 4, 1, 2, 4, 8, ...]

给你一个二维整数数组 queries ,其中 queries[i] = [fromi, toi, modi] ,你需要计算 (big_nums[fromi] * big_nums[fromi + 1] * ... * big_nums[toi]) % modi

请你返回一个整数数组 answer ,其中 answer[i] 是第 i 个查询的答案。

示例 1:

输入:queries = [[1,3,7]]
输出:[4]
解释:
只有一个查询。
big_nums[1..3] = [2,1,2] 。它们的乘积为 4。结果为 4 % 7 = 4。

示例 2:

输入:queries = [[2,5,3],[7,7,4]]
输出:[2,2]
解释:
有两个查询。
第一个查询:big_nums[2..5] = [1,2,4,1] 。它们的乘积为 8 。结果为 8 % 3 = 2。
第二个查询:big_nums[7] = 2 。结果为 2 % 4 = 2。

说明:

  • 1 <= queries.length <= 500
  • queries[i].length == 3
  • 0 <= queries[i][0] <= queries[i][1] <= 10^15
  • 1 <= queries[i][2] <= 10^5

思路

// todo

代码

性能

3133.数组最后一个元素的最小值

目标

给你两个整数 n 和 x 。你需要构造一个长度为 n 的 正整数 数组 nums ,对于所有 0 <= i < n - 1 ,满足 nums[i + 1] 大于 nums[i] ,并且数组 nums 中所有元素的按位 AND 运算结果为 x 。

返回 nums[n - 1] 可能的 最小 值。

示例 1

输入:n = 3, x = 4
输出:6
解释:
数组 nums 可以是 [4,5,6] ,最后一个元素为 6 。

示例 2

输入:n = 2, x = 7
输出:15
解释:
数组 nums 可以是 [7,15] ,最后一个元素为 15 。

说明

  • 1 <= n, x <= 10^8

思路

构造一个长度为 n 的单调递增数组 nums,要求数组所有元素按位与的结果为正整数 x,返回 nums[n - 1] 的最小值。

要使元素按位与的结果为 x,那么 x 中bit位为1的位置在元素中也必须为1。我们可以找到 x 中bit位为0的位置,从最低位开始置1,如果还不凑不够数组个数就将最高位置1,重新从最低位开始置1。

刚开始是按照上面的思路模拟着写的,非常容易出错。调试了半天发现,其实就是将 n - 1 的二进制表示填入 x 的二进制表示中的bit位为0的位置,如果不够就借用高位的0。之所以是 n -1 是因为 x 本身也算一个元素,0 ~ n - 1n 个元素。

官网题解也正是这个思路,不过实现简洁多了。主要是刚开始没有想清楚,其实根本不用讨论低位/高位,直接填就行了。

代码


/**
 * @date 2024-08-22 10:12
 */
public class MinEnd3133 {

    public long minEnd(int n, int x) {
        List<Integer> zeroIndex = new ArrayList<>(63);
        int i = 0;
        int tmp = x;
        // 记录0的位置
        while (tmp > 0) {
            if ((tmp & 1) == 0) {
                zeroIndex.add(i);
            }
            tmp >>= 1;
            i++;
        }
        long res = x;
        int zeroCnt = zeroIndex.size();
        long highBitsCnt;
        // 如果不含0,那么只能填高位
        if (zeroCnt == 0) {
            // 这个不应该全填1,应填n-1的二进制表示
            highBitsCnt = n - 1;
            while (highBitsCnt > 0) {
                if ((highBitsCnt & 1) == 1) {
                    res |= 1L << i;
                }
                i++;
                highBitsCnt >>= 1;
            }
            return res;
        }
        // 如果含0则计算其能表示的数字个数,下面是快速幂
        long oneLoopElementCnt = 1;
        tmp = zeroCnt;
        int base = 2;
        while (tmp > 0) {
            if ((tmp & 1) == 1) {
                oneLoopElementCnt = oneLoopElementCnt * base;
            }
            base *= base;
            tmp >>= 1;
        }
        // 低位需要填的个数
        long lowBitsCnt = n % oneLoopElementCnt - 1;
        if (lowBitsCnt == -1) {
            // 如果为-1,表示能够整除,将低位的0全置为1
            for (Integer index : zeroIndex) {
                res |= 1L << index;
            }
            // 如果低位能够填满数组则无需填高位
            if (n <= oneLoopElementCnt) {
                highBitsCnt = 0;
            } else {
                // 高位的计数需减1,是因为将低位全填1,这时已经完成了一个loop,例如n=4,x=2,oneLoopElementCnt 为2,n / oneLoopElementCnt = 2, (10 11) 110 111,我们只需要填充一个高位
                highBitsCnt = n / oneLoopElementCnt - 1;
            }
        } else {
            // 否则将需要填在低位的个数填入低位的0
            int j = 0;
            while (lowBitsCnt > 0) {
                if ((lowBitsCnt & 1) == 1) {
                    res |= 1L << zeroIndex.get(j);
                }
                j++;
                lowBitsCnt >>= 1;
            }
            // 如果低位能够填满数组则无需填高位
            if (n <= oneLoopElementCnt) {
                highBitsCnt = 0;
            } else {
                // 这里不需要减1,是因为n不能整除oneLoopElementCnt,多余位已经被舍去了,例如n=3,x=2,n / oneLoopElementCnt = 1
                highBitsCnt = n / oneLoopElementCnt;
            }
        }

        // 填充高位个数
        while (highBitsCnt > 0) {
            if ((highBitsCnt & 1) == 1) {
                // 出错点:如果写成1,会溢出,必须加上L
                res |= 1L << i;
            }
            i++;
            highBitsCnt >>= 1;
        }

        return res;
    }

}

性能

3007.价值和小于等于K的最大数字

目标

给你一个整数 k 和一个整数 x 。整数 num 的价值是它的二进制表示中在 x2x3x …… 等位置处 set bit(指在某数的二进制表示中值为 1 的二进制位) 的数目(从最低有效位开始)。下面的表格包含了如何计算价值的例子。

x num Binary Representation Price
1 13 000001101 3
2 13 000001101 1
2 233 011101001 3
3 13 000001101 1
3 362 101101010 2

num累加价值 是从 1num 的数字的 价值。如果 num 的累加价值小于或等于 k 则被认为是 廉价 的。

请你返回 最大 的廉价数字。

示例 1:

输入:k = 9, x = 1
输出:6
解释:由下表所示,6 是最大的廉价数字。
x num Binary Representation Price Accumulated Price
1 1 001 1 1
1 2 010 1 2
1 3 011 2 4
1 4 100 1 5
1 5 101 2 7
1 6 110 2 9
1 7 111 3 12

示例 2:

输入:k = 7, x = 2
输出:9
解释:由下表所示,9 是最大的廉价数字。
x num Binary Representation Price Accumulated Price
2 1 0001 0 0
2 2 0010 1 1
2 3 0011 1 2
2 4 0100 0 2
2 5 0101 0 2
2 6 0110 1 3
2 7 0111 1 4
2 8 1000 1 5
2 9 1001 1 6
2 10 1010 2 8

说明:

  • 1 <= k <= 10^15
  • 1 <= x <= 8

提示:

  • Binary search the answer.
  • In each step of the binary search you should calculate the number of the set bits in the ith position. Then calculate the sum of them.

思路

给定步长x,数字的价值定义为从最低有效位开始,以步长x遍历数字的二进制表示,并记录bit为1的个数。数字n的累加价值定义为 1 ~ n 的价值之和。给定数字k,求累加价值不超过k的最大数字。

先尝试模拟暴力求解。注意到返回值是 long 类型,说明n的规模超过了10^9,即便是 O(n) 的解法也会超时,并且每个数字都要循环bit位计数,肯定超时。我们需要要找一种 O(logn) 的解法。

提示说使用二分查找,问题的关键是如何直接计算出给定数字的累加价值。

// todo

代码

性能

3154.到达第 K 级台阶的方案数

目标

给你有一个 非负 整数 k 。有一个无限长度的台阶,最低 一层编号为 0 。

Alice 有一个整数 jump ,一开始值为 0 。Alice 从台阶 1 开始,可以使用 任意 次操作,目标是到达第 k 级台阶。假设 Alice 位于台阶 i ,一次 操作 中,Alice 可以:

  • 向下走一级到 i - 1 ,但该操作 不能 连续使用,如果在台阶第 0 级也不能使用。
  • 向上走到台阶 i + 2^jump 处,然后 jump 变为 jump + 1 。

请你返回 Alice 到达台阶 k 处的总方案数。

注意,Alice 可能到达台阶 k 处后,通过一些操作重新回到台阶 k 处,这视为不同的方案。

示例 1:

输入:k = 0
输出:2
解释:
2 种到达台阶 0 的方案为:
- Alice 从台阶 1 开始。
    执行第一种操作,从台阶 1 向下走到台阶 0 。
- Alice 从台阶 1 开始。
    执行第一种操作,从台阶 1 向下走到台阶 0 。
    执行第二种操作,向上走 20 级台阶到台阶 1 。
    执行第一种操作,从台阶 1 向下走到台阶 0 。

示例 2:

输入:k = 1
输出:4
解释:

4 种到达台阶 1 的方案为:
- Alice 从台阶 1 开始,已经到达台阶 1 。
- Alice 从台阶 1 开始。
    执行第一种操作,从台阶 1 向下走到台阶 0 。
    执行第二种操作,向上走 20 级台阶到台阶 1 。
- Alice 从台阶 1 开始。
    执行第二种操作,向上走 20 级台阶到台阶 2 。
    执行第一种操作,向下走 1 级台阶到台阶 1 。
- Alice 从台阶 1 开始。
    执行第一种操作,从台阶 1 向下走到台阶 0 。
    执行第二种操作,向上走 20 级台阶到台阶 1 。
    执行第一种操作,向下走 1 级台阶到台阶 0 。
    执行第二种操作,向上走 21 级台阶到台阶 2 。
    执行第一种操作,向下走 1 级台阶到台阶 1 。

说明:

0 <= k <= 10^9

思路

//todo

代码

性能

552.学生出勤记录II

目标

可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:

  • '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 次)。

示例 2:

输入:n = 1
输出:3

示例 3:

输入:n = 10101
输出:183236316

说明:

  • 1 <= n <= 10^5

思路

使用 A L P 三种字符组成长度为 n 的字符串,要求字符串中最多包含一个 'A',并且不能连续出现三个及以上的 'L',问满足条件的字符串有多少个。

很明显需要使用动态规划求解。定义状态 dp[i][hadAbsent][ithState] 表示长度为i,以ithState(0:L; 1:P; 2:A)结尾,hadAbsent(0 ~ i-1,包含1/不包含0)'A'的字符串的个数。

状态转移方程为

  • dp[i][0][0] = dp[i-2][0][0] + 2*dp[i-2][0][1] LPL PPL PLL
  • dp[i][0][1] = dp[i-1][0][0] + dp[i-1][0][1] LP PP
  • dp[i][0][2] = dp[i-1][0][0] + dp[i-1][0][1] LA PA
  • dp[i][1][0] = dp[i-2][1][0] + 2*dp[i-2][1][1] + 2*dp[i-2][0][2] + dp[i-1][0][2] (A)LPL (A)PPL (A)PLL ALL APL AL
  • dp[i][1][1] = dp[i-1][1][0] + dp[i-1][1][1] + dp[i-1][0][2] (A)LP (A)PP AP

初始条件需要提前计算:

  • dp[0][0][0] = 1; L
  • dp[0][0][1] = 1; P
  • dp[0][0][2] = 1; A
  • dp[1][0][0] = 2; LL PL
  • dp[1][0][1] = 2; LP PP
  • dp[1][0][2] = 2; LA PA
  • dp[1][1][0] = 1; AL
  • dp[1][1][1] = 1; AP

模运算(取余)满足以下规律:

  • (a + b + c) % mod = ((a % mod) + (b % mod) + (c % mod)) % mod
  • (a * b * c) % mod = ((a % mod) * (b % mod) * (c % mod)) % mod

代码

/**
 * @date 2024-08-19 9:53
 */
public class CheckRecord552 {
    private static final int MOD = 1000000007;

    public int checkRecord(int n) {
        if (n == 1) {
            return 3;
        }
        long[][][] dp = new long[n][2][3];
        dp[0][0][0] = 1;
        dp[0][0][1] = 1;
        dp[0][0][2] = 1;

        dp[1][0][0] = 2;
        dp[1][0][1] = 2;
        dp[1][0][2] = 2;
        dp[1][1][0] = 1;
        dp[1][1][1] = 1;

        for (int i = 2; i < n; i++) {
            int pre = i - 1;
            int prepre = i - 2;
            dp[i][0][0] = (dp[prepre][0][0] + 2 * dp[prepre][0][1]) % MOD;
            dp[i][0][1] = (dp[pre][0][0] + dp[pre][0][1]) % MOD;
            dp[i][0][2] = (dp[pre][0][0] + dp[pre][0][1]) % MOD;
            dp[i][1][0] = (dp[prepre][1][0] + 2 * dp[prepre][1][1] + 2 * dp[prepre][0][2] + dp[pre][0][2]) % MOD;
            dp[i][1][1] = (dp[pre][1][0] + dp[pre][1][1] + dp[pre][0][2]) % MOD;
        }
        return (int) ((dp[n - 1][0][0] + dp[n - 1][0][1] + dp[n - 1][0][2] + dp[n - 1][1][0] + dp[n - 1][1][1]) % MOD);
    }

}

性能

551.学生出勤记录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'

思路

记录缺勤总次数,判断连续迟到天数即可。

代码


/**
 * @date 2024-08-18 19:52
 */
public class CheckRecord551 {

    public boolean checkRecord(String s) {
        int n = s.length();
        int absent = 0;
        int late = 0;
        for (int i = 0; i < n; i++) {
            char c = s.charAt(i);
            if (c == 'A') {
                absent++;
                if (absent == 2) {
                    return false;
                }
            } else if (c == 'L') {
                late++;
                if (late == 3) {
                    return false;
                }
                continue;
            }
            late = 0;
        }
        return true;
    }
}

性能