6027. 统计数组中峰和谷的数量
给你一个下标从 0 开始的整数数组 nums 。如果两侧距 i 最近的不相等邻居的值均小于 nums[i] ,则下标 i 是 nums 中,某个峰的一部分。类似地,如果两侧距 i 最近的不相等邻居的值均大于 nums[i] ,则下标 i 是 nums 中某个谷的一部分。对于相邻下标 i 和 j ,如果 nums[i] == nums[j] , 则认为这两下标属于 同一个 峰或谷。
注意,要使某个下标所做峰或谷的一部分,那么它左右两侧必须 都 存在不相等邻居。
返回 nums 中峰和谷的数量。
示例 1:
输入:nums = [2,4,1,1,6,5] 输出:3 解释: 在下标 0 :由于 2 的左侧不存在不相等邻居,所以下标 0 既不是峰也不是谷。 在下标 1 :4 的最近不相等邻居是 2 和 1 。由于 4 > 2 且 4 > 1 ,下标 1 是一个峰。 在下标 2 :1 的最近不相等邻居是 4 和 6 。由于 1 < 4 且 1 < 6 ,下标 2 是一个谷。 在下标 3 :1 的最近不相等邻居是 4 和 6 。由于 1 < 4 且 1 < 6 ,下标 3 符合谷的定义,但需要注意它和下标 2 是同一个谷的一部分。 在下标 4 :6 的最近不相等邻居是 1 和 5 。由于 6 > 1 且 6 > 5 ,下标 4 是一个峰。 在下标 5 :由于 5 的右侧不存在不相等邻居,所以下标 5 既不是峰也不是谷。 共有 3 个峰和谷,所以返回 3 。
示例 2:
输入:nums = [6,6,5,5,4,1] 输出:0 解释: 在下标 0 :由于 6 的左侧不存在不相等邻居,所以下标 0 既不是峰也不是谷。 在下标 1 :由于 6 的左侧不存在不相等邻居,所以下标 1 既不是峰也不是谷。 在下标 2 :5 的最近不相等邻居是 6 和 4 。由于 5 < 6 且 5 > 4 ,下标 2 既不是峰也不是谷。 在下标 3 :5 的最近不相等邻居是 6 和 4 。由于 5 < 6 且 5 > 4 ,下标 3 既不是峰也不是谷。 在下标 4 :4 的最近不相等邻居是 5 和 1 。由于 4 < 5 且 4 > 1 ,下标 4 既不是峰也不是谷。 在下标 5 :由于 1 的右侧不存在不相等邻居,所以下标 5 既不是峰也不是谷。 共有 0 个峰和谷,所以返回 0 。
提示:
- 3 <= nums.length <= 100
- 1 <= nums[i] <= 100
思路:
模拟题
class Solution {
public int countHillValley(int[] nums) {
int cnt = 0;
for (int i = 0; i < nums.length; i ++) {
int l = i - 1, r = i + 1;
while (l >= 0 && nums[l] == nums[i])
l--;
while (r < nums.length && nums[r] == nums[i])
r++;
if (l >= 0 && r < nums.length && ((nums[l] > nums[i] && nums[r] > nums[i]) || (nums[l] < nums[i] && nums[r] < nums[i])))
cnt++;
i = r - 1;
}
return cnt;
}
}
6028. 统计道路上的碰撞次数
在一条无限长的公路上有 n 辆汽车正在行驶。汽车按从左到右的顺序按从 0 到 n - 1 编号,每辆车都在一个 独特的 位置。
给你一个下标从 0 开始的字符串 directions ,长度为 n 。directions[i] 可以是 ‘L’、’R’ 或 ‘S’ 分别表示第 i 辆车是向 左 、向 右 或者 停留 在当前位置。每辆车移动时 速度相同 。
碰撞次数可以按下述方式计算:
- 当两辆移动方向 相反 的车相撞时,碰撞次数加 2 。
- 当一辆移动的车和一辆静止的车相撞时,碰撞次数加 1 。
碰撞发生后,涉及的车辆将无法继续移动并停留在碰撞位置。除此之外,汽车不能改变它们的状态或移动方向。
返回在这条道路上发生的 碰撞总次数 。
示例 1:
输入:directions = “RLRSLL” 输出:5 解释: 将会在道路上发生的碰撞列出如下: - 车 0 和车 1 会互相碰撞。由于它们按相反方向移动,碰撞数量变为 0 + 2 = 2 。 - 车 2 和车 3 会互相碰撞。由于 3 是静止的,碰撞数量变为 2 + 1 = 3 。 - 车 3 和车 4 会互相碰撞。由于 3 是静止的,碰撞数量变为 3 + 1 = 4 。 - 车 4 和车 5 会互相碰撞。在车 4 和车 3 碰撞之后,车 4 会待在碰撞位置,接着和车 5 碰撞。碰撞数量变为 4 + 1 = 5 。 因此,将会在道路上发生的碰撞总次数是 5 。
示例 2:
输入:directions = “LLRR” 输出:0 解释: 不存在会发生碰撞的车辆。因此,将会在道路上发生的碰撞总次数是 0 。
提示:
- 1 <= directions.length <= 105
- directions[i] 的值为 ‘L’、’R’ 或 ‘S’
思路:
除了最长向左前缀和最长向右后缀外,其余车辆均会碰撞,去除那些一开始就是S状态的就是碰撞次数
比赛的时候写的有点麻烦,硬模拟了
class Solution {
public int countCollisions(String s) {
int n = s.length();
int i = 0, j = n - 1;
while (i < n && s.charAt(i) == 'L')
i++;
while (j >= 0 && s.charAt(j) == 'R')
j--;
int cnt = 0;
for (int k = i; k <= j; k++)
if (s.charAt(k) != 'S')
cnt++;
return cnt;
}
}
6029. 射箭比赛中的最大得分
Alice 和 Bob 是一场射箭比赛中的对手。比赛规则如下:
- Alice 先射 numArrows 支箭,然后 Bob 也射 numArrows 支箭。
- 分数按下述规则计算:
- 箭靶有若干整数计分区域,范围从 0 到 11 (含 0 和 11)。
- 箭靶上每个区域都对应一个得分 k(范围是 0 到 11),Alice 和 Bob 分别在得分 k 区域射中 ak 和 bk 支箭。如果 ak >= bk ,那么 Alice 得 k 分。如果 ak < bk ,则 Bob 得 k 分
- 如果 ak == bk == 0 ,那么无人得到 k 分。
- 例如,Alice 和 Bob 都向计分为 11 的区域射 2 支箭,那么 Alice 得 11 分。如果 Alice 向计分为 11 的区域射 0 支箭,但 Bob 向同一个区域射 2 支箭,那么 Bob 得 11 分。
给你整数 numArrows 和一个长度为 12 的整数数组 aliceArrows ,该数组表示 Alice 射中 0 到 11 每个计分区域的箭数量。现在,Bob 想要尽可能 最大化 他所能获得的总分。
返回数组 bobArrows ,该数组表示 Bob 射中 0 到 11 每个 计分区域的箭数量。且 bobArrows 的总和应当等于 numArrows 。
如果存在多种方法都可以使 Bob 获得最大总分,返回其中 任意一种 即可。
示例 1:
输入:numArrows = 9, aliceArrows = [1,1,0,1,0,0,2,1,0,1,2,0] 输出:[0,0,0,0,1,1,0,0,1,2,3,1] 解释:上表显示了比赛得分情况。 Bob 获得总分 4 + 5 + 8 + 9 + 10 + 11 = 47 。 可以证明 Bob 无法获得比 47 更高的分数。
示例 2:
输入:numArrows = 3, aliceArrows = [0,0,1,0,0,0,0,0,0,0,0,2] 输出:[0,0,0,0,0,0,0,0,1,1,1,0] 解释:上表显示了比赛得分情况。 Bob 获得总分 8 + 9 + 10 = 27 。 可以证明 Bob 无法获得比 27 更高的分数。
提示:
- 1 <= numArrows <= 105
- aliceArrows.length == bobArrows.length == 12
- 0 <= aliceArrows[i], bobArrows[i] <= numArrows
- sum(aliceArrows[i]) == numArrows
思路:
二进制枚举 找最优解
class Solution {
public int[] maximumBobPoints(int x, int[] a) {
int n = 12;
int[] res = new int[n];
int max = 0, v = 0;
for (int i = 0; i < 1 << n; i++) {
int sum = 0;
int cnt = 0;
for (int j = 0; j < n; j++) {
if ((i >> j & 1) == 1) {
cnt += a[j] + 1;
sum += j;
}
}
if (cnt <= x && sum > max) {
max = sum;
v = i;
}
}
int cnt = 0;
int sum = 0;
for (int i = 0; i < n; i++) {
if ((v >> i & 1) == 1) {
res[i] = a[i] + 1;
cnt += res[i];
sum += i;
}
}
// System.out.println(sum);
if (x > cnt) res[0] += x - cnt;
return res;
}
}
6030. 由单个字符重复的最长子字符串
给你一个下标从 0 开始的字符串 s 。另给你一个下标从 0 开始、长度为 k 的字符串 queryCharacters ,一个下标从 0 开始、长度也是 k 的整数 下标 数组 queryIndices ,这两个都用来描述 k 个查询。
第 i 个查询会将 s 中位于下标 queryIndices[i] 的字符更新为 queryCharacters[i] 。
返回一个长度为 k 的数组 lengths ,其中 lengths[i] 是在执行第 i 个查询 之后 s 中仅由 单个字符重复 组成的 最长子字符串 的 长度 。
示例 1:
输入:s = “babacc”, queryCharacters = “bcb”, queryIndices = [1,3,3] 输出:[3,3,4] 解释: - 第 1 次查询更新后 s = “bbb_acc” 。由单个字符重复组成的最长子字符串是 “bbb” ,长度为 3 。 - 第 2 次查询更新后 s = “bbbccc“ 。由单个字符重复组成的最长子字符串是 “bbb” 或 “ccc”,长度为 3 。 - 第 3 次查询更新后 s = “_bbbb_cc” 。由单个字符重复组成的最长子字符串是 “bbbb” ,长度为 4 。 因此,返回 [3,3,4] 。
示例 2:
输入:s = “abyzz”, queryCharacters = “aa”, queryIndices = [2,1] 输出:[2,3] 解释: - 第 1 次查询更新后 s = “aba_zz“ 。由单个字符重复组成的最长子字符串是 “zz” ,长度为 2 。 - 第 2 次查询更新后 s = “_aaa_zz” 。由单个字符重复组成的最长子字符串是 “aaa” ,长度为 3 。 因此,返回 [2,3] 。
提示:
- 1 <= s.length <= 105
- s 由小写英文字母组成
- k == queryCharacters.length == queryIndices.length
- 1 <= k <= 105
- queryCharacters 由小写英文字母组成
- 0 <= queryIndices[i] < s.length
思路:
线段树板子题
单点修改,区间查询
class Solution {
final int N = 100010;
int n, m;
Node[] tr = new Node[4 * N];
char[] ch;
public int[] longestRepeating(String s, String qc, int[] qidx) {
ch = s.toCharArray();
n = ch.length;
m = qidx.length;
build(1, 0, n - 1);
int[] res = new int[m];
for (int i = 0; i < m; i++) {
modify(1, qidx[i], qc.charAt(i));
res[i] = tr[1].max;
}
return res;
}
void build(int u, int l, int r) {
if (l == r) {
tr[u] = new Node(l, r);
tr[u].lmax = tr[u].rmax = tr[u].max = tr[u].len = 1;
} else {
tr[u] = new Node(l, r);
int mid = l + r >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void pushup(int u) {
Node left = tr[u << 1], right = tr[u << 1 | 1];
tr[u].len = left.len + right.len;
tr[u].max = Math.max(left.max, right.max);
tr[u].lmax = left.lmax;
tr[u].rmax = right.rmax;
int mid = tr[u].l + tr[u].r >> 1;
if (ch[mid] == ch[mid + 1]) {
tr[u].max = Math.max(tr[u].max, left.rmax + right.lmax);
if (left.len == left.lmax)
tr[u].lmax = Math.max(tr[u].lmax, left.len + right.lmax);
if (right.len == right.rmax)
tr[u].rmax = Math.max(tr[u].rmax, right.len + left.rmax);
}
}
void modify(int u, int idx, char c) {
if (tr[u].l == idx && tr[u].r == idx) {
ch[idx] = c;
return;
} else {
int mid = tr[u].l + tr[u].r >> 1;
if (idx <= mid) modify(u << 1, idx, c);
else modify(u << 1 | 1, idx, c);
pushup(u);
}
}
}
class Node {
int l, r;
int max, len;
int lmax, rmax;
Node(int l, int r) {
this.l = l;
this.r = r;
}
}