leetcode最少移动此时使数组元素相等

注意:此题是借助中位数而不是平均数

因为每次操作可以使元素减1或加1,则所有元素排序之后必定是往中间靠拢,当所以元素的值都和中卫数相等时,操作完成。

证明如下:

1)设为2n+1个数,中位数是m,排序之后如下

*******a m b ********,其中a<=m<=b,m左右两边分别都有N个数

设m左边的数变成m的代价是x,m右边的数变成m代价是y,则选择中位数的代价是x+y,

现在选择a,则m左边的数变成a的代价是x-(m-a)*n,m右边的数变成a的代价是y+(m-a)*n,相加为x+y,但m也需要变成a,则总的代价是x+y+m-a,

若a<m,则选择a时代价大于选择m;若a==m,则两者代价相等。

现在选择b,则m左边的数变成a的代价是x+(b-m)*n,m右边的数变成a的代价是y-(b-m)*n,相加为x+y,但m也需要变成b,则总的代价是x+y+b-m,

若m<b,则选择b的代价大于m;若b==m,则两者代价相等。

2)设为2n个数,排序之后如下

*******a  b ********,其中a<=b,a左边,b右边分别都有N-1个数

如果选择把所有的数变成a,设a左边的数变成a的代价为x,b右边的数变成b的代价为y,则总的代价为x+y+b-a,因为b也要变成a.

如果选择把所有数变成b,则a左边的数变成b的代价为x+(b-a)*(n-1),b右边的代价为y-(b-a)*(n-1),则总的代价仍然为x+y+b-a,因为a也要变成b。

即选取中位数合理,且中位数直接去nums[len/2]即可,然后计算每个数与中位数的差值。

还可以排序之后left指向0,right指向len-1,直接计算nums[right]-nums[left]的累加和

因为nums[right]-nums[len/2]+nums[len/2]-nums[left]=nums[right]-nums[left]。

a<=x<=b,则a,b都往x靠拢的操作数为x-a+b-x=b-a

代码如下:

class Solution {
public:
    int minMoves2(vector<int>& nums) {
      //每次移动只能让一个元素加1或者减1,应该是中位数,而不是平均数
      int len=nums.size();
      sort(nums.begin(),nums.end());
      int res=0;
      int left=0,right=len-1;
      while(left<right)
        res+=nums[right--]-nums[left++];
     return res;
    }
};
发布了191 篇原创文章 · 获赞 3 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/qq_38196982/article/details/104797957