1. 程式人生 > 實用技巧 >LeetCode——最小移動次數使陣列元素相等

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;
    }
}