思路:
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;
}
};
看不懂差分的同学可以看看这篇哦~