leetcode.1674 使数组互补的最少操作次数 - 差分

1674. 使数组互补的最少操作次数

思路:

res[x] 表示当nums[i]+nums[n-1-i]==x时,所需的操作数

以下简称 a=nums[i]   b=nums[n-1-i]

所以答案就是最小的res[x]值

x取值范围为[ 2,2*limit ] 

  • 2——只要把a和b都改为1  x==2
  • limit*2——只要把a和b都改为limit   x==2*limit

计算数组里每一对a b的操作数 用差分数组进行对res区间的修改

  • 先把最大范围[2,2*limit]操作数置为2
  • [1+min(a,b),limit+max(a,b)]操作数为1  也就是在上一个区间的基础上-1
  • 【1+较小数,limit+较大数】该区间内的a b能保证在limit范围内只更改a或b
  • [a+b,a+b]区间内不用更改就满足,操作数为0,也就是在上一个区间的基础上-1

差分数组:res[i]=diff[1]+diff[2]+……+diff[i]

想给res的某个区间[l,r] +c 只需要给其差分数组diff[l]+=c diff[r+1]-=c即可

最后只要枚举每个res[x]  2~2*limit 求最小即可

class Solution {
public:
    int minMoves(vector<int>& nums, int limit) {
        
        int n=nums.size();
        vector<int> diff(2*limit+2,0);
        //因为res[x] x范围为[2,2*limit] 则res数组范围为[2,2*limit+1] 因为差分数组需要r+1 则diff数组开到2*limit+2
        for(int i=0;i<n/2;i++) 
        {
            int a=nums[i],b=nums[n-i-1];

            //[2,2*limit]区间内操作数先全部置为2 也就是a和b都更改
            //给res[2,2*limit]区间+2
            int l=2,r=limit*2;
            diff[l]+=2,diff[r+1]-=2;

            //在上一区间的基础上 [1+min(a,b),limit+max(a,b)]内操作数更新为1 也就是只更改a或b
            //给res[1+min(a,b),limit+max(a,b)]区间-1
            l=1+min(a,b),r=limit+max(a,b);
            diff[l]+=-1,diff[r+1]-=-1;

            //在上一区间的基础上[a+b,a+b]操作数更新为0 当a+b==a+b时不用更改
            //给res[a+b,a+b]区间-1
            l=a+b,r=a+b;
            diff[l]+=-1,diff[r+1]-=-1;
        }
        int sum=0,res=0x3f3f3f3f;
        for(int i=2;i<=limit*2;i++)
        {
            sum+=diff[i];
            res=min(res,sum);
        }
        return res;
    }
};

 看不懂差分的同学可以看看这篇哦~

【算法基础复习1】差分_Roye_ack的博客-CSDN博客

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值