LeetCode Weekly Contest 285

LeetCode Weekly Contest 285

排名1515 / 7501。

6027. 统计数组中峰和谷的数量 [EASY]

给你一个下标从 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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/* 
审题:先遍历一次剔除重复元素,再遍历一次判断波峰波谷
*/
class Solution {
public:
int countHillValley(vector<int>& nums) {
int result = 0;
vector<int> numsTmp;
numsTmp.push_back(nums[0]);
for (int i = 1; i < nums.size(); i++) {
if (nums[i] == nums[i - 1]) {
continue;
}
numsTmp.push_back(nums[i]);
}
// for (int i = 0; i < numsTmp.size(); i++) {
// cout << numsTmp[i] << ", ";
// }
// cout << endl;
for (int i = 1; i < numsTmp.size() - 1; i++) {
if ((i + 1 <= numsTmp.size() - 1) && (numsTmp[i] > numsTmp[i - 1]) && (numsTmp[i] > numsTmp[i + 1])) {
result++;
}
if ((i + 1 <= numsTmp.size() - 1) && (numsTmp[i] < numsTmp[i - 1]) && (numsTmp[i] < numsTmp[i + 1])) {
result++;
}
}
return result;
}
};

6028. 统计道路上的碰撞次数 [MEDIUM]

在一条无限长的公路上有 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’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
/*
审题:写的状态转移,代码比较多。实际掐头(去掉左边的'L')去尾(去掉右边的'R'),中间的所有的非'S'的车最后都是停止的,那么只要统计中间的所有的非'S'的车的数量就可以('RL'两辆都停所以+2)
https://leetcode-cn.com/problems/count-collisions-on-a-road/solution/jie-lun-ti-san-xing-gao-ding-by-endlessc-bvnw/
*/
class Solution {
public:
enum State {
INIT = -1,
LEFT = 0,
RIGHT = 1,
STATIC = 2
};
int countCollisions(string directions) {
int result = 0;
int state = INIT;
int add = 0;
for (int i = 0; i < directions.size(); i++) {
// cout << i << ", " << directions[i] << ", " << result << endl;
if (directions[i] == 'L') {
switch (state) {
case INIT:
state = LEFT;
continue;
case LEFT:
continue;
case RIGHT:
result += 2 + add;
add = 0;
state = STATIC;
continue;
case STATIC:
result += 1;
state = STATIC;
continue;
}
} else if (directions[i] == 'R') {
switch (state) {
case INIT:
case LEFT:
case STATIC:
state = RIGHT;
continue;
case RIGHT:
add++;
continue;
}
} else {
switch (state) {
case INIT:
state = STATIC;
continue;
case STATIC:
continue;
case LEFT:
state = STATIC;
continue;
case RIGHT:
result += 1 + add;
add = 0;
state = STATIC;
continue;
}
}
}
return result;
}
};

6029. 射箭比赛中的最大得分 [MEDIUM]

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
审题:我用dfs做的,有个[binary enum](https://leetcode-cn.com/problems/maximum-points-in-an-archery-competition/solution/er-jin-zhi-mei-ju-by-endlesscheng-rjul/),学到了

class Solution {
public:
int maxPoint = 0;
vector<int> bobArrows_;
void dfs(const vector<int>& aliceArrows, int start, int resArrows, int sumPoint, vector<int>& bobArrows) {
if (resArrows < 0) {
return;
}
if (sumPoint >= maxPoint) {
maxPoint = sumPoint;
bobArrows_ = bobArrows;
}
for (int j = start; j >= 0; j--) {
if (j == 0) {
bobArrows[j] = resArrows;
} else {
bobArrows[j] = aliceArrows[j] + 1;
}
dfs(aliceArrows, j - 1, resArrows - bobArrows[j], sumPoint + j, bobArrows);
bobArrows[j] = 0;
}
}

vector<int> maximumBobPoints(int numArrows, vector<int>& aliceArrows) {
vector<int> bobArrows(12, 0);
dfs(aliceArrows, 11, numArrows, 0, bobArrows);
return bobArrows_;
}
};

6030. 由单个字符重复的最长子字符串 [HARD]

给你一个下标从 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 = “bbbacc” 。由单个字符重复组成的最长子字符串是 “bbb” ,长度为 3 。
  • 第 2 次查询更新后 s = “bbbccc” 。由单个字符重复组成的最长子字符串是 “bbb” 或 “ccc”,长度为 3 。
  • 第 3 次查询更新后 s = “bbbbcc” 。由单个字符重复组成的最长子字符串是 “bbbb” ,长度为 4 。
    因此,返回 [3,3,4] 。

示例 2:
输入:s = “abyzz”, queryCharacters = “aa”, queryIndices = [2,1]
输出:[2,3]
解释:

  • 第 1 次查询更新后 s = “abazz” 。由单个字符重复组成的最长子字符串是 “zz” ,长度为 2 。
  • 第 2 次查询更新后 s = “aaazz” 。由单个字符重复组成的最长子字符串是 “aaa” ,长度为 3 。
    因此,返回 [2,3] 。

提示:
1 <= s.length <= 105
s 由小写英文字母组成
k == queryCharacters.length == queryIndices.length
1 <= k <= 105
queryCharacters 由小写英文字母组成
0 <= queryIndices[i] < s.length

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
审题:写的暴力,果然超时

评论的题解:
1.线段树https://leetcode-cn.com/problems/longest-substring-of-one-repeating-character/solution/by-endlesscheng-qpbw/
2. 模拟https://leetcode-cn.com/problems/longest-substring-of-one-repeating-character/solution/by-tsreaper-7axn/

class Solution {
public:
inline int getLongest(const string& s) {
int longest = 0;
char state = s[0];
int cnt = 1;
for (int i = 1; i < s.size(); i++) {
if (s[i] == s[i - 1]) {
cnt++;
} else {
if (cnt > longest) {
longest = cnt;
}
cnt = 1;
}
// cout << i << ", " << s[i] << ", " << longest << ", " << cnt << endl;
}
if (cnt > longest) {
longest = cnt;
}
// cout << longest << ", " << s << endl;
return longest;
}

vector<int> longestRepeating(string s, string queryCharacters, vector<int>& queryIndices) {
vector<int> result(queryIndices.size(), 0);
for (int i = 0; i < queryIndices.size(); i++) {
s[queryIndices[i]] = queryCharacters[i];
result[i] = getLongest(s);
}
return result;
}
};
Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×