leetcode 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 中的所有值互不相同

分析:先将所有的机器人按照 positions 位置从左到右排序,并用一个栈,记录当前有多少个向右走的机器人。排好序之后,从左到右遍历所有的机器人,如果这个机器人是向右走的,则先存入栈中;如果是向左走的,则先检查栈是否为空,如果为空,则这个机器人不会发生碰撞,可以幸存,如果栈不为空,则取出栈顶的机器人,对比健康度进行碰撞,直到栈为空或者这个机器人被移除为止。检查完所有的机器人后,栈里剩下的机器人都是幸存的机器人。按照原来的输入顺序排序后返回即可。

cpp 复制代码
class Solution {
public:
    typedef struct node
    {
        int pos,hea,ind;
        char dir;
    }node;
    static bool cmp(const node a,const node b)
    {
        return a.pos<b.pos;
    }
    static bool cmp2(const node a,const node b)
    {
        return a.ind<b.ind;
    }
    vector<int> survivedRobotsHealths(vector<int>& positions, vector<int>& healths, string directions) {
        int n=positions.size();
        vector<node>vec,res;
        for(int i=0;i<n;++i)
        {
            node temp;temp.pos=positions[i],temp.hea=healths[i],temp.dir=directions[i],temp.ind=i;
            vec.push_back(temp);
        }
        sort(vec.begin(),vec.end(),cmp);
        stack<node>sta;
        for(int i=0;i<n;++i)
        {
            if(vec[i].dir=='L')
            {
                if(sta.size()==0)res.push_back(vec[i]);
                else
                {
                    node rob=sta.top();sta.pop();
                    if(rob.hea>vec[i].hea)rob.hea--,sta.push(rob);
                    else if(rob.hea<vec[i].hea)vec[i].hea--,i--;
                }
            }
            else if(vec[i].dir=='R')sta.push(vec[i]);
        }
        while(!sta.empty())
            res.push_back(sta.top()),sta.pop();
        sort(res.begin(),res.end(),cmp2);
        
        vector<int>ans;
        for(int i=0;i<res.size();++i)
            ans.push_back(res[i].hea);
        return ans;
    }
};
相关推荐
圣保罗的大教堂3 小时前
leetcode 1406. 石子游戏 III 困难
leetcode
带多刺的玫瑰11 小时前
Leecode#15刷题之三数之和
算法·leetcode·职场和发展
圣保罗的大教堂11 小时前
leetcode 877. 石子游戏 中等
leetcode
shehuiyuelaiyuehao13 小时前
算法32,连续数组,前缀和+哈希表
算法·leetcode·职场和发展
Navigator_Z15 小时前
LeetCode //C - 1223. Dice Roll Simulation
c语言·算法·leetcode
Tisfy16 小时前
LeetCode 2058.找出临界点之间的最小和最大距离:遍历+遇到极值则更新(这种题谁空间复杂度不是O(1)啊)
linux·数据库·leetcode·链表·题解·模拟·遍历
小欣加油16 小时前
Leetcode2058 找出临界点之间的最小和最大距离
数据结构·c++·算法·leetcode·职场和发展
CoderYanger17 小时前
A.每日一题:3345. 最小可整除数位乘积 I
java·数据结构·程序人生·算法·leetcode·面试·学习方法
玖玥拾17 小时前
LeetCode 1 两数之和
算法·leetcode·职场和发展
旖旎夜光17 小时前
LeetCode 974:和可被 K 整除的子数组(前缀和) —— 题解
数据结构·c++·算法·leetcode·前缀和