最小移动到相等数组元素

Minimum Moves to Equal Array Elements

本文关键字:数组元素 移动      更新时间:2023-10-16

给定一个大小为n的非空整数数组,找出使所有数组元素相等所需的最小移动次数,其中移动是将n- 1个元素增加1。

的例子:

输入:(1、2、3)

输出:3

解释:只需要三次移动(记住每次移动增加两个元素):

[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]讨论

我试着用蛮力,但是我不能给出一个正确的算法,循环不变量是不正确的。有没有人可以解释一下,这样我就可以提高我的算法技能了?

bool checkEquality(vector<int> &num)
{
    for (int j = 1; j < num.size(); j++)
    {
        if (num[j] != num[j - 1])
        {
            return false;
        }
    }
    return true;
}

    int main() {
        vector<int> num = { 1, 2,3 };
        int numMoves = num.size() - 1;
        int prev = 0;
        int j = 0;
        while(!checkEquality(num))
        { 
            for (int i = prev; i < num.size(); i++)
            {
                for ( j = i; j < numMoves; j++)
                {
                    num[j]++;
                }
                if (i == num.size())
                {
                    prev = j;
                    j = 0;
                }
                else
                prev = 0;
            }
        }
    }

首先,您不需要对这个问题进行暴力破解。有一个线性时间解,答案是

sum(num) - min(num) * length(num)
<标题>编辑

解释

增加除一个以外的所有值等于减少该值。我们用这个来代替。多少个单元素减数才能使所有元素相等?没有指向在当前最小值以下递减,那么单元素递减多少次才能等于当前最小值呢?只需取当前值(和)与我们想要的值(n乘以最小值)之差。

下面是c++代码

int minMoves(vector<int>& nums) {
    if(nums.empty()) return 0;
    int n = nums.size();
    int sum = 0;
    int Min = INT_MAX;
    for(int i = 0; i < n; ++i) {
        sum += nums[i];
        Min = min(Min, nums[i]);
    }
    return (sum - Min * n);
}

或者甚至在一行中:

return accumulate(nums.begin(), nums.end(), 0) - nums.size() * *min_element(nums.begin(), nums.end());

你可以看到这个问题是减少一个元素而不是增加其他元素。

现在问题就简单多了。您只需要添加每个元素,直到它达到数组中的最大元素。我将解决它如下:

int findMax(vector<int> &num)
{
    int maximum=num[0];
    for(int i=1;i<num.size();i++)
    {
        if(maximum<num[i])
            maximum=num[i];
    }
    return maximum;
}
int main()
{
    vector<int> num;
    num.push_back(1);
    num.push_back(2);
    num.push_back(3);
    int max_val=findMax(num);
    int answer=0;
    for(int i=0;i<num.size();i++)
    {
        answer+=max_val-num[i];
    }
    cout<<answer<<endl;
}

一个简单的方法:

    int minMoves(vector<int>& nums) 
    {
         sort(nums.begin(), nums.end());
         int moves=0, n=nums.size();                   
         for(int i=0; i<n; i++)
         {
            moves += (nums[n-1-i] - nums[0]);
         }
         return moves;  
    }

一个非常简单的方法:-

int minMoves(vector<int>& nums) {
    int sum=0;
    int small= *min_element(nums.begin(),nums.end());
    for(int i=0;i<nums.size();i++)
    {
        sum=sum+(nums[i]-small);
    }
    return sum;
}