力扣3224.使差值相等的最少数组改动次数
枚举法
-
枚举差值x的数值,max(q,k-p)为修改一个能得到的上限
- 用cnt存qp差值,cnt2存差值上限
- 有cnt[x]对无需修改
- n/2 - cnt[x]对至少修改一个
- cnt2[0] + cnt[1] + … + cnt2[x-1]需要再修改一个
- 设sum2 = cnt2[0] + cnt[1] + … + cnt2[x-1]
- 因此ans = n/2 - cnt[x] + sum2
-
class Solution { public: int minChanges(vector<int>& nums, int k) { vector<int> cnt(k+1),cnt2(k+1); int n = nums.size(); for(int i=0;i<n/2;i++) { int p = nums[i],q = nums[n-i-1]; if(p > q) swap(p,q); cnt[q-p] ++; cnt2[max(q,k-p)] ++; } int ans = n; int sum2 = 0; for(int x=0;x<=k;x++) { ans = min(ans,n/2 - cnt[x] + sum2); sum2 += cnt2[x]; } return ans; } };
差分数组
-
对于每一对(q,p),求出差值x和最大可实现差值mx
- 他对差值x的贡献为**(0,x-1)修改一次,x不修改,(x+1,mx)修改一次,(mx,k)修改两次**
- 因此考虑差分数组存每种差值x情况需要修改的次数
-
class Solution { public: int minChanges(vector<int>& nums, int k) { vector<int> d(k+2); int n = nums.size(); for(int i=0;i<n/2;i++) { int p = nums[i],q = nums[n-i-1]; if(p > q) swap(p,q); int x = q - p; int mx = max(q,k - p); //[0,x-1]改一次 d[0] ++; d[x] --; //[x,mx]改一次 d[x+1] ++; d[mx + 1] --; //[mx,k]改两次 d[mx + 1] += 2; } //求前缀和 for(int i=0;i<d.size()-1;i++) d[i+1] += d[i]; return ranges::min(d); } };