力扣每日一题

2731. 移动机器人 - 力扣(LeetCode) 

暴力模拟如下 :

class Solution {
public:
    const int mod = 1e9 + 7;
    int sumDistance(vector<int>& nums, string s, int d) 
    {
        using i64 = long long;
        int n = nums.size();
        while(d--)
        {
            for(int i = 0;i < n;i++)
            {
                nums[i] += (s[i] == 'R' ? 1 : -1);
                if(i && nums[i] == nums[i - 1])
                swap(s[i], s[i - 1]);
            }
        }
        i64 ans = 0;
        for(int i = 0; i < n; i++)
        {
            for(int j = i + 1;j < n;j++)
            ans = (ans % mod + (abs(v[i] - v[j]) % mod)) % mod;
        }
        return ans; 
    }
};

 

看数据范围d == 1e9

可见该题解在处理d秒时的时间复杂度应当不超过O(n)

因此:上解需要优化

 当我们碰撞的时候:

                if(i && nums[i] == nums[i - 1])
                swap(s[i], s[i - 1]);

交换俩者的方向,那也等于交换俩个机器人的效果,于是我们可以忽略碰撞影响,直接求d秒无碰撞的相对位置即可。

举一个简单的例子:

A = 0 == >> R

B = 2 == >> L

d = 10;

在1秒的时候交换方向

A = 1 == >> L

B = 1 == >> R

10s后:

A = -8 == >> L

B =  10 == >> R;

直接求相对距离

A = 10 == >> R

B = -8 == >> L

因此直接求d秒无碰撞的相对位置对最终答案无影响

此时: 由数据范围nums最大可为2e9,d 最大为1e9 >> 2147483647

爆int,需要i64数据类型进行存储

 可得:

class Solution {
public:
    const int mod = 1e9 + 7;
    int sumDistance(vector<int>& nums, string s, int d) 
    {
        using i64 = long long;
        int n = nums.size();
        vector<i64> v(n);
        for(int i = 0;i < n; i++)
        v[i] = nums[i] + (s[i] == 'R' ? d : -d);
        i64 ans = 0;
        for(int i = 0; i < n; i++)
        {
            for(int j = i + 1;j < n;j++)
            ans = (ans % mod + (abs(v[i] - v[j]) % mod)) % mod;
        }
        return ans; 
    }
};

再看数据范围 

 

 n的范围为[2,1e5]  

仅看ans求值的第一轮循环1e5 * (1e5 - 1)显然超时

对于ans的求值过程有这么一种情况

对于任意 i [0,n]前有i个数,后有n - i个数 == >> i * (n - i)个数对都会进行一次加(v[i] - v[i- 1])的值

可得:

class Solution {
public:
    const int mod = 1e9 + 7;
    int sumDistance(vector<int>& nums, string s, int d) 
    {
        using i64 = long long;
        int n = nums.size();
        vector<i64> v(n);
        for(int i = 0;i < n; i++)
        v[i] = nums[i] + (s[i] == 'R' ? d : -d);
        sort(v.begin(),v.end());
        i64 ans = 0;
        for (int i = 1; i < n; i++) 
        {
            ans = ((v[i] - v[i - 1]) * i % mod * (n - i) + ans) % mod;
        }
        return ans; 
    }
};

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值