【每日一题】移动机器人

文章目录

  • Tag
  • 题目来源
  • 题目解读
  • 解题思路
    • 方法一:脑筋急转弯+排序
  • 写在最后

Tag

【脑筋急转弯+排序】【数组】【2023-10-10】


题目来源

2731. 移动机器人

【每日一题】移动机器人_第1张图片

题目解读

每个机器人按照一开始的设定向左或者向右移动,遇到另一个机器人就转换移动的方向,问一定时间之间任意两个机器人之间的距离和是多少。


解题思路

方法一:脑筋急转弯+排序

我们可以这样考虑,如果两个机器人发生了碰撞,那么原来向左移动的机器人现在向右移动了,原来向右移动的机器人向左移动了。从单个机器人来看移动的方向改变了,但是从整体来看机器人的移动没有变化。初始状态向右移动的机器人数量和现在发生碰撞后向右的移动的机器人数量一样,向左移动的也是。那么我们就可以当做所有机器人都没有发生碰撞,统计按照初始设定的运动方向,每个机器人可以走到的位置,用一个数组 pos 表示。

接下来就是计算任意两个机器人之间的距离。

我们先给 pos 进行升序排序,然后从枚举相邻元素之间的距离,实际上就是进行 for 循环。对于循环的当前的变量 i,当前的间隔为 pos[i] - pos[i-1],下标 i 左侧有 i 个元素,i 的右侧有 n-i 个元素(包括 i 本身)。当前的距离要计算 i * (n-1) 次。

我们以下图为例进行说明为什么要当前的距离要加上 i * (n - i) 次。图中 i = 2,当前的距离为 pos[2] - pos[1],图中以绿色加粗的实线表示。i 左侧的所有元素(有 i 个)都要计算和 i 右侧(包括自己)所有元素的距离,每一次计算的一部分都是当前距离,也算是了贡献法了,当前距离一共贡献了 i * (n - i)

【每日一题】移动机器人_第2张图片

实现代码

class Solution {
public:
    static const int mod = 1e9 + 7;
    int sumDistance(vector<int>& nums, string s, int d) {
        int n = s.size();
        vector<long long> pos(n);
        for (int i = 0; i < n; ++i) {
            if (s[i] == 'L') {
                pos[i] += (long long)nums[i] - d;
            }
            else {
                pos[i] += (long long)nums[i] + d;
            }
        }
        sort(pos.begin(), pos.end());
        long long res = 0;
        for (int i = 1; i < n; ++i) {
            res += (pos[i] - pos[i-1]) * i % mod * (n - i) % mod;
            res %= mod;
        }
        return res;
    }
};

复杂度分析

时间复杂度: O ( n l o g n ) O(nlogn) O(nlogn) n n n 为数组 nums 的长度。计算 pos 的时间复杂度为 O ( n ) O(n) O(n),对 pos 排序的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),因此总的时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)

空间复杂度: O ( n l o g n ) O(nlogn) O(nlogn)。 每个机器人最后停留的位置 pos 占用的空间为 O ( n ) O(n) O(n),对 pos 排序的空间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),因此总的空间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn)


写在最后

如果文章内容有任何错误或者您对文章有任何疑问,欢迎私信博主或者在评论区指出 。

如果大家有更优的时间、空间复杂度方法,欢迎评论区交流。

最后,感谢您的阅读,如果感到有所收获的话可以给博主点一个 哦。

你可能感兴趣的:(LeetCode每日一题,脑筋急转弯+排序,数组,2023-10-10,C++,算法)