
题目描述
现有 n 个机器人,编号从 1 开始,每个机器人包含在路线上的位置、健康度和移动方向。
给你下标从 0 开始的两个整数数组 positions、healths 和一个字符串 directions(directions[i] 为 'L' 表示 向左 或 'R' 表示 向右)。 positions 中的所有整数 互不相同 。
所有机器人以 相同速度 同时 沿给定方向在路线上移动。如果两个机器人移动到相同位置,则会发生 碰撞 。
如果两个机器人发生碰撞,则将 健康度较低 的机器人从路线中 移除 ,并且另一个机器人的健康度 减少 1 。幸存下来的机器人将会继续沿着与之前 相同 的方向前进。如果两个机器人的健康度相同,则将二者都从路线中移除。
请你确定全部碰撞后幸存下的所有机器人的 健康度 ,并按照原来机器人编号的顺序排列。即机器人 1 (如果幸存)的最终健康度,机器人 2 (如果幸存)的最终健康度等。 如果不存在幸存的机器人,则返回空数组。
在不再发生任何碰撞后,请你以数组形式,返回所有剩余机器人的健康度(按机器人输入中的编号顺序)。
注意:位置 positions 可能是乱序的。
示例 1:

输入:positions = [5,4,3,2,1], healths = [2,17,9,15,10], directions = "RRRRR"
输出:[2,17,9,15,10]
解释:在本例中不存在碰撞,因为所有机器人向同一方向移动。所以,从第一个机器人开始依序返回健康度,[2, 17, 9, 15, 10] 。
示例 2:

输入:positions = [3,5,2,6], healths = [10,10,15,12], directions = "RLRL"
输出:[14]
解释:本例中发生 2 次碰撞。首先,机器人 1 和机器人 2 将会碰撞,因为二者健康度相同,二者都将被从路线中移除。接下来,机器人 3 和机器人 4 将会发生碰撞,由于机器人 4 的健康度更小,则它会被移除,而机器人 3 的健康度变为 15 - 1 = 14 。仅剩机器人 3 ,所以返回 [14] 。
示例 3:

输入:positions = [1,2,5,6], healths = [10,10,11,11], directions = "RLRL"
输出:[]
解释:机器人 1 和机器人 2 将会碰撞,因为二者健康度相同,二者都将被从路线中移除。机器人 3 和机器人 4 将会碰撞,因为二者健康度相同,二者都将被从路线中移除。所以返回空数组 [] 。
提示:
1 <= positions.length == healths.length == directions.length == n <= 105 1 <= positions[i], healths[i] <= 109 directions[i] == 'L' 或 directions[i] == 'R' positions 中的所有值互不相同
解法
方法一:栈模拟
我们首先将机器人按照位置从小到大排序,用一个数组 \(\textit{idx}\) 存储排序后的机器人编号。然后我们使用一个栈来模拟碰撞过程:
- 从左到右遍历 \(\textit{idx}\) 中的机器人编号 \(i\),如果 \(directions[i]\) 是向右移动,则将 \(i\) 入栈。
- 如果 \(directions[i]\) 是向左移动,则与栈顶的向右移动的机器人发生碰撞,直到栈为空或当前机器人被移除。
- 如果栈顶机器人健康度大于当前机器人,则当前机器人被移除,栈顶机器人健康度减 1。
- 如果栈顶机器人健康度小于当前机器人,则栈顶机器人被移除,当前机器人健康度减 1,并继续与新的栈顶机器人发生碰撞。
- 如果两者健康度相同,则两者都被移除。
最后我们返回所有健康度大于 0 的机器人健康度。
时间复杂度 \(O(n \times \log n)\),空间复杂度 \(O(n)\)。其中 \(n\) 是机器人的数量。
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 | class Solution:
def survivedRobotsHealths(self, positions, healths, directions):
idx = sorted(range(len(positions)), key=lambda i: positions[i])
stk = []
for i in idx:
if directions[i] == "R":
stk.append(i)
continue
while stk and healths[i]:
j = stk[-1]
if healths[j] > healths[i]:
healths[j] -= 1
healths[i] = 0
elif healths[j] < healths[i]:
healths[i] -= 1
healths[j] = 0
stk.pop()
else:
healths[i] = healths[j] = 0
stk.pop()
break
return [h for h in healths if h > 0]
|
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 | class Solution {
public List<Integer> survivedRobotsHealths(int[] positions, int[] healths, String directions) {
int n = positions.length;
Integer[] idx = new Integer[n];
Arrays.setAll(idx, i -> i);
Arrays.sort(idx, (a, b) -> positions[a] - positions[b]);
Deque<Integer> stk = new ArrayDeque<>();
for (int i : idx) {
if (directions.charAt(i) == 'R') {
stk.push(i);
continue;
}
while (!stk.isEmpty() && healths[i] > 0) {
int j = stk.peek();
if (healths[j] > healths[i]) {
healths[j]--;
healths[i] = 0;
} else if (healths[j] < healths[i]) {
healths[i]--;
healths[j] = 0;
stk.pop();
} else {
healths[i] = healths[j] = 0;
stk.pop();
break;
}
}
}
List<Integer> ans = new ArrayList<>();
for (int h : healths) {
if (h > 0) {
ans.add(h);
}
}
return ans;
}
}
|
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 | class Solution {
public:
vector<int> survivedRobotsHealths(vector<int>& positions, vector<int>& healths, string directions) {
int n = positions.size();
vector<int> idx(n);
iota(idx.begin(), idx.end(), 0);
sort(idx.begin(), idx.end(), [&](int a, int b) {
return positions[a] < positions[b];
});
vector<int> stk;
for (int i : idx) {
if (directions[i] == 'R') {
stk.push_back(i);
continue;
}
while (!stk.empty() && healths[i] > 0) {
int j = stk.back();
if (healths[j] > healths[i]) {
healths[j]--;
healths[i] = 0;
} else if (healths[j] < healths[i]) {
healths[i]--;
healths[j] = 0;
stk.pop_back();
} else {
healths[i] = healths[j] = 0;
stk.pop_back();
break;
}
}
}
vector<int> ans;
for (int h : healths) {
if (h > 0) {
ans.push_back(h);
}
}
return ans;
}
};
|
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 | func survivedRobotsHealths(positions []int, healths []int, directions string) []int {
n := len(positions)
idx := make([]int, n)
for i := range idx {
idx[i] = i
}
sort.Slice(idx, func(i, j int) bool {
return positions[idx[i]] < positions[idx[j]]
})
stk := []int{}
for _, i := range idx {
if directions[i] == 'R' {
stk = append(stk, i)
continue
}
for len(stk) > 0 && healths[i] > 0 {
j := stk[len(stk)-1]
if healths[j] > healths[i] {
healths[j]--
healths[i] = 0
} else if healths[j] < healths[i] {
healths[i]--
healths[j] = 0
stk = stk[:len(stk)-1]
} else {
healths[i], healths[j] = 0, 0
stk = stk[:len(stk)-1]
break
}
}
}
ans := []int{}
for _, h := range healths {
if h > 0 {
ans = append(ans, h)
}
}
return ans
}
|
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 | function survivedRobotsHealths(
positions: number[],
healths: number[],
directions: string,
): number[] {
const n = positions.length;
const idx = Array.from({ length: n }, (_, i) => i).sort((a, b) => positions[a] - positions[b]);
const stk: number[] = [];
for (const i of idx) {
if (directions[i] === 'R') {
stk.push(i);
continue;
}
while (stk.length && healths[i] > 0) {
const j = stk[stk.length - 1];
if (healths[j] > healths[i]) {
healths[j]--;
healths[i] = 0;
} else if (healths[j] < healths[i]) {
healths[i]--;
healths[j] = 0;
stk.pop();
} else {
healths[i] = healths[j] = 0;
stk.pop();
break;
}
}
}
return healths.filter(h => h > 0);
}
|
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 | impl Solution {
pub fn survived_robots_healths(
positions: Vec<i32>,
mut healths: Vec<i32>,
directions: String
) -> Vec<i32> {
let n = positions.len();
let mut idx: Vec<usize> = (0..n).collect();
idx.sort_by_key(|&i| positions[i]);
let dirs = directions.as_bytes();
let mut stk: Vec<usize> = Vec::new();
for &i in &idx {
if dirs[i] == b'R' {
stk.push(i);
continue;
}
while let Some(&j) = stk.last() {
if healths[i] == 0 {
break;
}
if healths[j] > healths[i] {
healths[j] -= 1;
healths[i] = 0;
break;
} else if healths[j] < healths[i] {
healths[i] -= 1;
healths[j] = 0;
stk.pop();
} else {
healths[i] = 0;
healths[j] = 0;
stk.pop();
break;
}
}
}
healths.into_iter().filter(|&h| h > 0).collect()
}
}
|
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 | /**
* @param {number[]} positions
* @param {number[]} healths
* @param {string} directions
* @return {number[]}
*/
var survivedRobotsHealths = function (positions, healths, directions) {
const n = positions.length;
const idx = Array.from({ length: n }, (_, i) => i).sort((a, b) => positions[a] - positions[b]);
const stk = [];
for (const i of idx) {
if (directions[i] === 'R') {
stk.push(i);
continue;
}
while (stk.length && healths[i] > 0) {
const j = stk[stk.length - 1];
if (healths[j] > healths[i]) {
healths[j]--;
healths[i] = 0;
} else if (healths[j] < healths[i]) {
healths[i]--;
healths[j] = 0;
stk.pop();
} else {
healths[i] = healths[j] = 0;
stk.pop();
break;
}
}
}
return healths.filter(h => h > 0);
};
|