LeetCode——最小移动次数使数组元素相等

Q:给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数。每次移动将会使 n - 1 个元素增加 1。

示例:
输入:
[1,2,3]
输出:
3
解释:
只需要3次移动(注意每次移动会增加两个元素的值):
[1,2,3] => [2,3,3] => [3,4,3] => [4,4,4]

A:

  1. 暴力法的基础上,考虑到为了让最小元素等于最大元素,至少需要加 k 次。在那之后,最大元素可能发生变化。因此,我们一次性增加增量 k=max-min,并将移动次数增加 k。然后,对整个数组进行扫描,找到新的最大值和最小值,重复这一过程直到最大元素和最小元素相等。
    要注意的是考虑可能最大值有多个
    但超时了。
    public int minMoves(int[] nums) {
        if (nums.length <= 1)
            return 0;
        int count = 0;
        while (true) {
            int minIndex = 0;
            int maxIndex = 0;
            for (int i = 0; i < nums.length; i++) {
                if (nums[i] < nums[minIndex])
                    minIndex = i;
                if (nums[i] > nums[maxIndex])
                    maxIndex = i;
            }
            int max = nums[maxIndex];
            int min = nums[minIndex];
            if (min == max) {
                break;
            }
            int temp = max - min;
            count += temp;
            for (int i = 0; i < nums.length; i++) {
                if (i != maxIndex)
                    nums[i] += temp;
            }
        }
        return count;
    }
  1. 数学法
    将除了一个元素之外的全部元素+1,等价于将该元素-1,因为我们只对元素的相对大小感兴趣。因此,该问题简化为需要进行的减法次数。显然,我们只需要将所有的数都减到最小的数即可。为了找到答案,我们不需要真的操作这些元素。只需要(moves = sum_{i=0}^{n-1}(a[i]-min))即可
public class Solution {
    public int minMoves(int[] nums) {
        int moves = 0, min = Integer.MAX_VALUE;
        for (int i = 0; i < nums.length; i++) {
            min = Math.min(min, nums[i]);
        }
        for (int i = 0; i < nums.length; i++) {
            moves += nums[i] - min;
        }
        return moves;
    }
}
原文地址:https://www.cnblogs.com/xym4869/p/13428533.html