LeetCode 2751. 机器人碰撞

2751. 机器人碰撞

现有 n 个机器人,编号从 1 开始,每个机器人包含在路线上的位置、健康度和移动方向。

给你下标从 0 开始的两个整数数组 positionshealths 和一个字符串 directionsdirections[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 <= 10^5
  • 1 <= positions[i], healths[i] <= 10^9
  • directions[i] == 'L' 或 directions[i] == 'R'
  • positions 中的所有值互不相同

提示 1

Process the robots in the order of their positions to ensure that we process the collisions correctly.


提示 2

To optimize the solution, use a stack to keep track of the surviving robots as we iterate through the positions.


提示 3

Instead of simulating each collision, check the current robot against the top of the stack (if it exists) to determine if a collision occurs.

解法1:栈

类似题型:LeetCode 735. 小行星碰撞-CSDN博客

LeetCode 2211. 统计道路上的碰撞次数-CSDN博客

算法逻辑

  1. 数据结构选择:使用数组来存储机器人的信息,包括编号、位置、健康度和移动方向。
  2. 排序:首先根据机器人的位置对列表进行排序,确保按顺序处理碰撞。
  3. 栈的使用:使用栈来跟踪幸存的机器人。栈顶是当前位置最近的机器人。
  4. 模拟碰撞:遍历排序后的机器人数组,对于每个机器人,检查是否与栈顶的机器人发生碰撞:
    • 如果当前机器人向左移动('L'),并且栈顶机器人向右移动('R'),则进行碰撞检测。
    • 如果两个机器人健康度相同,它们都会被淘汰。
    • 如果当前机器人健康度低于栈顶机器人,当前机器人被淘汰,栈顶机器人健康度减1。
    • 如果当前机器人健康度高于栈顶机器人,栈顶机器人被淘汰,当前机器人健康度减1。
  5. 更新栈:根据碰撞结果更新栈,可能包括弹出栈顶元素或将当前机器人压入栈。
  6. 结果生成:遍历结束后,栈中剩余的元素即为幸存的机器人。根据机器人的原始编号对栈进行排序,然后提取健康度作为结果。

算法步骤

  1. 初始化:创建一个数组 robots,包含每个机器人的编号、位置、健康度和移动方向。
  2. 排序:按照机器人的位置对 robots 数组进行排序。
  3. 初始化栈:创建一个空栈 stack
  4. 遍历机器人数组
    • 对于每个机器人,执行以下步骤:
      • 设置live标志为True,表示机器人初始状态为存活。
      • 检查栈顶机器人(如果有)和当前机器人是否满足碰撞条件。
      • 如果发生碰撞,根据健康度决定哪个机器人存活或都被淘汰,并更新live标志和栈。
  5. 压栈:如果live标志为True,将当前机器人压入栈。
  6. 排序并提取结果:遍历结束后,根据机器人编号对栈进行排序,然后提取每个机器人的健康度,返回结果。

Java版:

class Solution {
    public List<Integer> survivedRobotsHealths(int[] positions, int[] healths, String directions) {
        int n = positions.length;
        int[][] robots = new int[n][4];
        for (int i = 0; i < n; i++) {
            robots[i][0] = i;
            robots[i][1] = positions[i];
            robots[i][2] = healths[i];
            robots[i][3] = directions.charAt(i) == 'L' ? 0 : 1;
        }
        Arrays.sort(robots, (a, b) -> a[1] - b[1]);
        Deque<int[]> stack = new LinkedList<>();
        for (int i = 0; i < n; i++) {
            boolean live = true;
            while (live && robots[i][3] == 0 && !stack.isEmpty() && stack.peek()[3] == 1) {
                if (robots[i][2] == stack.peek()[2]) {
                    live = false;
                    stack.pop();
                } else if (robots[i][2] < stack.peek()[2]) {
                    live = false;
                    stack.peek()[2]--;
                } else {
                    stack.pop();
                    robots[i][2]--;
                }
            }
            if (live) {
                stack.push(robots[i]);
            }
        }
        List<int[]> list = new ArrayList<>(stack);
        Collections.sort(list, (a, b) -> a[0] - b[0]);
        return list.stream().map(robot -> robot[2]).collect(Collectors.toList());
    }
}

Python3版:

class Solution:
    def survivedRobotsHealths(self, positions: List[int], healths: List[int], directions: str) -> List[int]:
        robots = [[i, pos, health, direction] for i, (pos, health, direction) in enumerate(zip(positions, healths, directions))]
        robots.sort(key = lambda x: x[1])
        stack = []
        for robot in robots:
            live = True
            while live and robot[3] == 'L' and stack and stack[-1][3] == 'R':
                if robot[2] == stack[-1][2]:
                    live = False
                    stack.pop()
                elif robot[2] < stack[-1][2]:
                    live = False
                    stack[-1][2] -= 1
                else: 
                    stack.pop()
                    robot[2] -= 1
            if live:
                stack.append(robot)
        stack.sort(key = lambda x: x[0])
        return [s[2] for s in stack]
复杂度分析
  • 时间复杂度:O(nlogn),其中 n 为 positions 的长度。瓶颈在排序上。
  • 空间复杂度:O(n)。
  • 22
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值