1. 程式人生 > >[Math_Medium]462. Minimum Moves to Equal Array Elements II

[Math_Medium]462. Minimum Moves to Equal Array Elements II

member 數值 sort 一個數 element ini 如果 str 順序

原題462. Minimum Moves to Equal Array Elements II

題目大意:

給你一串數字,對於每個數字,一次性可以移動一步(數值增加1或者減小1),請問如何在最小的步伐數內使所有的數字都相等

Example

Input:
[1,2,3]
Output:
2
Explanation:
Only two moves are needed (remember each move increments or decrements one element):
[1,2,3] => [2,2,3] => [2,2,2]

解題思路:

  1. 錯誤思路:我的第一想法是求出這一串數字的平均數,再用每一個數減去這個平均數,求和,即輸出最短步伐,提交,WA,錯誤例子為[1,0,0,8,6],這裏應設為1,而不是平均數
  2. 正確思路:我們先把這一列數按從小到大的順序排序,把基準數k從最小數字開始,顯然此時不是最優解,如果我們增加k,比k大的數字的步伐都會減1,比k小的數字的步伐都會加1,當k左右的數字一樣多的時候,步伐最小。
    k-a[1]+k-a[2]+k-a[3]+...+a[N-3]-k+a[N-2]-k+a[N-1]-k,當+k和-k的數目一樣多的時候,k就會被抵消,這樣就是後面的數減前面的數,這裏要註意是奇數個還是偶數個

    代碼1:

class Solution {
public:
    int minMoves2(vector<int>& nums) {
        sort(nums.begin(),nums.end());
        int ans=0,mid=0;
        if(nums.size()%2)
            mid=(nums.size()+1)/2;
        else
            mid=nums.size()/2;
        mid-=1;
        for(int i=0;i<mid;i++)
            ans-=(nums[i]);
        for(int i=mid+1;i<nums.size();i++)
            ans+=(nums[i]);
        if(nums.size()%2==0)
            ans-=nums[mid];
        return ans;
    }
};

改良代碼:對於奇數個,中間那個數不用參與運算,即自己減自己為0;對於偶數個,中間那個數視為左邊的數,要參與運算;所以可以使用(nums.size()+1)/2,即若size為奇數,上面式子增加1,若為偶數,值不變,(相對於size/2)

class Solution{
    public:
    int minMoves2(vector<int>& nums)
    {
        sort(nums.begin(),nums.end());
        int mid=nums.size()/2,ans=0;
        for(int i=0;i<mid;i++)
            ans-=nums[i];
        for(int i=(nums.size()+1)/2;i<nums.size();i++)//使用(size()+1)/2,如果size是奇數,那麽值會+1,即從下一項開始;如果是偶數,值不變,仍然當前項
            ans+=nums[i];
        return ans;
    }
};    

[Math_Medium]462. Minimum Moves to Equal Array Elements II