最小操作次数使数组元素相等

标签: 数组 数学

难度: Medium

给你一个长度为 n 的整数数组,每次操作将会使 n - 1 个元素增加 1 。返回让数组所有元素相等的最小操作次数。

示例 1:

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

示例 2:

输入:nums = [1,1,1]
输出:0

提示:

  • n == nums.length
  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109
  • 答案保证符合 32-bit 整数

Submission

运行时间: 31 ms

内存: 16.9 MB

class Solution:
    def minMoves(self, nums: List[int]) -> int:
        return sum(nums) - len(nums) * min(nums)

Explain

本题可以转换思路:每次操作将 n - 1 个元素增加 1,等价于每次操作将 1 个元素减少 1。因此,要使所有元素相等,只需要将所有元素减少到数组中的最小值。所以,最小操作次数就是所有元素与最小元素的差值之和。

时间复杂度: O(n)

空间复杂度: O(1)

class Solution:
    def minMoves(self, nums: List[int]) -> int:
        # 计算数组中的最小值
        min_val = min(nums)
        # 计算所有元素与最小值的差值之和
        return sum(nums) - len(nums) * min_val

Explore

这种逻辑依据在于等效的目标变化。在这道题中,使数组所有元素相等的操作可以从两个角度来看:一是增加n-1个元素使其接近最大值,二是减少一个元素使其接近最小值。当你每次增加n-1个元素的值时,实际上是在相对地减小那个没有被增加的元素的值(在视觉上)。换句话说,每次增加大多数元素的同时不增加一个特定元素,相当于所有元素的平均水平上升了,而那个未增加的元素相对于其他元素就减少了。因此,从减少的角度看问题更简单,直接计算将所有元素减少到最小值所需的总步骤数,能够直观地反映操作的实质。

是的,该解法适用于包含负数的情况。在计算操作次数时,关键在于计算所有元素与最小元素的差值之和。无论最小元素是正数、零还是负数,元素间的差值总和都是不变的。因此,即使数组中包含负数,最小操作次数仍然正确地反映了将所有元素减少到最小值所需的总操作次数。

在此问题中,减少到数组中的最小值是最优解,因为每次操作你只能选择减少一个元素,而目标是让所有元素值相等。最小值是数组中自然界限,因为任何小于此的操作会导致至少一个元素需要额外的增加操作来达到新的目标值,这与题目要求相矛盾。因此,选择最小值作为目标是因为这是最自然且操作次数最少的选择。

在Python中,整数类型具有自动处理大数的能力,因此在理论上不会出现传统意义上的整数溢出问题。但是,在其他一些编程语言中,如C++或Java,需要考虑数据类型的最大和最小界限,可能会遇到溢出问题。在这些情况下,应当使用足够大的数据类型(如长整型)或者进行额外的检查来确保计算的安全。在Python中,只要内存足够,就可以安全地处理非常大的值。