liko 2731. 移动机器人

题目描述

有一些机器人分布在一条无限长的数轴上,他们初始坐标用一个下标从 0 开始的整数数组 nums 表示。当你给机器人下达命令时,它们以每秒钟一单位的速度开始移动。

给你一个字符串 s ,每个字符按顺序分别表示每个机器人移动的方向。‘L’ 表示机器人往左或者数轴的负方向移动,‘R’ 表示机器人往右或者数轴的正方向移动。

当两个机器人相撞时,它们开始沿着原本相反的方向移动。

请你返回指令重复执行 d 秒后,所有机器人之间两两距离之和。由于答案可能很大,请你将答案对 109 + 7 取余后返回。

注意:

  • 对于坐标在 i 和 j 的两个机器人,(i,j) 和 (j,i) 视为相同的坐标对。也就是说,机器人视为无差别的。
  • 当机器人相撞时,它们 立即改变 它们的前进方向,这个过程不消耗任何时间。
  • 当两个机器人在同一时刻占据相同的位置时,就会相撞。
  • 例如,如果一个机器人位于位置 0 并往右移动,另一个机器人位于位置 2 并往左移动,下一秒,它们都将占据位置 1,并改变方向。再下一秒钟后,第一个机器人位于位置 0 并往左移动,而另一个机器人位于位置 2 并往右移动。
  • 例如,如果一个机器人位于位置 0 并往右移动,另一个机器人位于位置 1 并往左移动,下一秒,第一个机器人位于位置 0 并往左行驶,而另一个机器人位于位置 1 并往右移动。

做题情况

  1. 做出来且思路与标答一致 ☑
  2. 做出来但思路较为复杂
  3. 有思路,但时间复杂度较高无法通过
  4. 没有思路

自己的想法:碰撞+排序+求解两两之间的距离

第一个难点为对于碰撞的处理。在进行碰撞时,两个机器人均改变方向,有点像动能守恒中的两个小球。在动能守恒中,一个小球a静止,与小球a完全相同的小球b撞向小球a。发生碰撞之后,小球b立刻静止,小球a以与小球b相同的速度,方向运动。对于这个实例,我们可以看成小球a与小球b发生交换,或者小球b“穿过”小球a继续运动。
机器人碰撞也是同理,我们可以将碰撞看成无视空间的穿梭,即不发生碰撞,两者就像什么事都没有发生一样继续运动。
第二个难题是求解两两之间的距离。由于一个可能有10^5个小球,因此时间复杂度最高为O(nlogn)。这里我们可以用数据归纳法的思路,或者说是秦九韶乘法的思想,求每个点到前面所有点的距离,求这个距离时我们可以根据上一个点的结果来进行求解。
当然在进行求和之前我们需要将所有小球位置从小到大进行排序。

标答:

同自己的想法

实际代码

class Solution {
public:
    int sumDistance(vector<int>& nums, string s, int d) 
    {
        //由于速度都是一致的,所以正常行走是不会出现相撞的问题。
        //换言之,我们不需要考虑碰撞带来的问题
        int n=nums.size();
        for (int i=0;i<n;++i)
        {
            if (s[i]=='L') nums[i]-=d;
            else nums[i]+=d;
        }
        long long res=0;
        long long last=0;
        sort(nums.begin(),nums.end());
        for (long long i=1;i<n;++i)
        {
            long long sum=(last+i*((long long)nums[i]-nums[i-1])%1000000007)%1000000007;
            res=(res+sum)%1000000007;
            last=sum;
        }
        return (int)res%1000000007;
    }
};

总结

对时间复杂度的运用:
对于一个数组,我们首先看时间复杂度是如何卡的,除了卡O(n)的以外,以及数组顺序不能动的情况下,我们都可以尝试将数组进行排序。
对于这道题,d的范围取到了10^9,那么显然这个值最多是O(n)的,或者是不影响时间复杂度的。
可以通过对时间复杂度的应用来对可选的算法进行限制,可以减少很多思考量。
int与long long:
当数组量很大的时候,这个地方总是容易出错。我们需要保证所有的int值不能超,在运算的过程中同样不能超。这个比较细节,所以最好一开始就确定好把什么变量用long long表示,直接避免这样的问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值