欢迎大家加QQ群:623375442,可以方便群里面交流。
这周题目很简单,第一题是第三题的弱化版本。我们直接从第二题开始。
100182. Maximum Points After Enemy Battles
给你一个下标从 0 开始的整数数组 enemyEnergies ,它表示一个下标从 0 开始的敌人能量数组。
同时给你一个整数 currentEnergy ,它表示你一开始拥有的能量值总量。
你一开始的分数为 0 ,且一开始所有的敌人都未标记。
你可以通过以下操作 之一 任意次(也可以 0 次)来得分:
- 选择一个 未标记 且满足 currentEnergy >= enemyEnergies[i] 的敌人 i 。在这个操作中:
- 你会获得 1 分。
- 你的能量值减少 enemyEnergies[i] ,也就是说 currentEnergy = currentEnergy - enemyEnergies[i] 。
- 如果你目前 至少 有 1 分,你可以选择一个 未标记 的敌人 i 。在这个操作中:
- 你的能量值增加 enemyEnergies[i] ,也就是说 currentEnergy = currentEnergy + enemyEnergies[i] 。
- 敌人 i 被标记 。
请你返回通过以上操作,最多 可以获得多少分。
测试样例:
输入:enemyEnergies = [3,2,2], currentEnergy = 2
输出:2
解释:通过以下操作可以得到最大得分 3 分:
- 对敌人 1 使用第一种操作:points 增加 1 ,currentEnergy 减少 2 。所以 points = 1 且 currentEnergy = 0 。
- 对敌人 0 使用第二种操作:currentEnergy 增加 3 ,敌人 0 被标记。所以 points = 1 ,currentEnergy = 3 ,被标记的敌人包括 [0] 。
- 对敌人 2 使用第一种操作:points 增加 1 ,currentEnergy 减少 2 。所以 points = 2 且 currentEnergy = 1 ,被标记的敌人包括[0] 。
- 对敌人 2 使用第二种操作:currentEnergy 增加 2 ,敌人 2 被标记。所以 points = 2 ,currentEnergy = 3 且被标记的敌人包括 [0, 2] 。
- 对敌人 1 使用第一种操作:points 增加 1 ,currentEnergy 减少 2 。所以 points = 3 ,currentEnergy = 1 ,被标记的敌人包括 [0, 2] 。
解答:阅读理解题,本身很简单。寻找整个数组的最小值(这就是获取点数最好的enemy),然后类和剩下的所有数。有个特殊情况需要注意,如果currentEnergy小于最小值,那么无论如何都不能获取点数,这个时候需要直接退出。
class Solution {
public long maximumPoints(int[] enemyEnergies, int currentEnergy) {
long sum = currentEnergy;
int len = enemyEnergies.length, min = Integer.MAX_VALUE;
for (int n : enemyEnergies) {
sum += n;
min = Math.min(min, n);
}
if (currentEnergy < min) {
return 0;
}
sum -= min;
return sum / min;
}
}
100351. Alternating Groups II
给你一个整数数组 colors 和一个整数 k ,colors表示一个由红色和蓝色瓷砖组成的环,第 i 块瓷砖的颜色为 colors[i] :
- colors[i] == 0 表示第 i 块瓷砖的颜色是 红色 。
- colors[i] == 1 表示第 i 块瓷砖的颜色是 蓝色 。
环中连续 k 块瓷砖的颜色如果是 交替 颜色(也就是说除了第一块和最后一块瓷砖以外,中间瓷砖的颜色与它 左边 和 右边 的颜色都不同),那么它被称为一个 交替 组。
请你返回 交替 组的数目。
注意 ,由于 colors 表示一个 环 ,第一块 瓷砖和 最后一块 瓷砖是相邻的。
测试样例:
输入:colors = [0,1,0,1,0], k = 3
输出:3
解释:0,1,2为头的三个连续数组都是交替数组。
解答:利用前缀和来判断当前位置为结尾,最长的连续交替数组长度。如果最长长度大于k,那么计数器+1。注意是循环数组,所以还需要对0 - (k - 1)位置特判一下。
class Solution {
public int numberOfAlternatingGroups(int[] colors, int k) {
int alter = 0, res = 0;
for (int i = 0; i < colors.length; ++i) {
if (i == 0 || colors[i] == colors[i - 1]) {
alter = 0;
}
++alter;
if (alter >= k) {
++res;
}
}
for (int i = 0; i < k - 1; ++i) {
if (colors[i] == colors[(i - 1 + colors.length) % colors.length]) {
alter = 0;
}
++alter;
if (alter >= k) {
++res;
}
}
return res;
}
}
100338. Number of Subarrays With AND Value of K
给你一个整数数组 nums 和一个整数 k ,请你返回 nums 中有多少个子数组满足:子数组中所有元素按位 AND 的结果为 k 。
测试样例:
输入:nums = [1,1,1], k = 1
输出:6
解释:所有子数组都只含有元素 1 。
解答:与的特性,碰到某一位碰到第一个0之后,无论如何,这一位都没办法转成1了。按照这个特性,我们遍历数组,并记录每个二进制位最后一个0出现的位置。利用这个位置,和k的二进制情况,就能计算出满足要求的各个区间。
class Solution {
public long countSubarrays(int[] nums, int k) {
long res = 0;
int[] mem = new int[30];
for (int i = 0; i < 30; ++i) {
mem[i] = -1;
}
for (int i = 0; i < nums.length; ++i) {
// 记录区间
int[] range = {0, i};
for (int j = 0; j < 30; ++j) {
// 记录最后一个0出现的位置
if (!isMark(nums[i], j)) {
mem[j] = i;
}
// 更新区间情况
if (isMark(k, j)) {
range[0] = Math.max(range[0], mem[j] + 1);
} else {
range[1] = Math.min(range[1], mem[j]);
}
}
res += Math.max(range[1] - range[0] + 1, 0);
}
return res;
}
private boolean isMark(int num, int offset) {
int tmp = (num >> offset) & 1;
return tmp == 1;
}
}