【问题标题】:Minimum count to make equal Array使数组相等的最小计数
【发布时间】:2020-08-22 06:35:35
【问题描述】:

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

Example:

Input:
[1,2,3]

Output:
3

说明:

Only three moves are needed (remember each move increments two elements):

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

链接有以下工作解决方案:

class Solution {
    public int minMoves(int[] nums) {
       int total=0, least=numbers[0];
        for (int i = 0; i < numbers.length; i++) {
            if (numbers[i] < least) {
                least = numbers[i];
            }
            total = total + numbers[i];
        }
        return total - least * numbers.length; 
    }
}

这里least 是数组中的最小值,total 是数组中所有元素的总和。

但我想知道total - least * numbers.length 的值是如何解决这个问题的。这是什么公式?有人可以解释一下吗?

【问题讨论】:

    标签: java algorithm


    【解决方案1】:

    '将 n - 1 个元素递增 1' 等于 '将 1 个元素递减 1(并且每个元素递增,但没有任何意义)'。

    您需要减少每个元素与最小值之间的差异,以使所有元素的最小值相等。

    所以,首先你应该从数组中找到最小值,然后得到所有元素的总和,然后减去最小元素乘以元素的数量。

    【讨论】:

    • 第一段看不懂,(and increment each element, but it doesn't have any sense)'. You need to decrement each element on the difference between it and the minimum.
    • 这是两个不同的句子。括号中的文字是撇号中的说明文字。第二句是解释算法。您需要计算 Σ(a[i]-min) 其中 a[i] - i 数组中的元素,min - 数组中的最小值。
    【解决方案2】:

    好吧,从“模”的角度考虑,递增数组的 n-1 个元素与递减数组的单个值相同(在此问题的上下文中)。例如,如果将 [1;1;1;2] 的前 3 个元素递增到 [2;2;2;2],则与递减最后一个元素完全相同: [1;1;1;2 ] 变为 [1;1;1;1],满足问题的条件。

    因此,问题变得更容易理解了:每次移动都可以减少一个元素。因此,您需要减少列表中的所有元素,直到它们等于列表的最小元素。然后,移动次数变为S - length * min,因为您必须减少 S 次才能使所有元素变为 0,但您可以通过达到只有最小值的数组来节省一些移动 (length * min)

    【讨论】:

      【解决方案3】:

      // We have number 123
      // Algorythm is simple: (add all digits to each other)
      // and substract (smallest digit * quantity of digits)
      let moves = (1 + 2 + 3) - (1*3);
      console.log(moves);
      
      // 622
      moves = (6 + 2 + 2) - (2*3);
      console.log(moves);
      
      // 183
      moves = (1 + 8 + 3) - (1*3);
      console.log(moves);

      所以我们可以编写简单的函数来计算数字的移动

      // Moves function
      const getMoves = (num) => {
        // Get summ of all digits
        const sum = String(num).split('').reduce((a, c) => Number(a) + Number(c));
        // Get minimum digit
        const min = String(num).split('').reduce((a, c) => a > c ? c : a);
        // Get number length
        const nl = String(num).length;
        // Calculate and return moves
        return sum - (min * nl);
      };
      
      // Test
      console.log(getMoves(123));
      console.log(getMoves(622));
      console.log(getMoves(183));

      最后,编写函数的替代方法来处理数组

      // Moves function
      const getMoves = (arr) => {
        const sum = arr.reduce((a, c) => a + c);
        const min = arr.reduce((a, c) => a > c ? c : a);
        return sum - (min * arr.length);
      };
      
      // Test
      console.log(getMoves([1,2,3]));
      console.log(getMoves([6,2,2]));
      console.log(getMoves([1,8,3]));

      【讨论】:

        【解决方案4】:

        我一直在想公式-

        number of moves = sum total - least * numbers.length
        

        这就是我尝试和理解的方式。假设我们有 3 个数字 - a、b、c。这些数字的最小值是a。现在,我们可以将这些数字的总和写成 -

        Sum Total = a + b + c = 3a + (b - a) + (c - a)
        

        总移动数应该是其他数字之间的差值之和。所以,公式变成了 -

        Sum Total = 3a + number of moves
        

        因此,结果是-

        number of moves = Sum Total - 3a
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-10-23
          • 2021-03-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-02-27
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多