leetcode每日一题系列-最小操作次数使数组元素相等-「贪心法」

316 阅读2分钟

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

[博客链接]

菜🐔的学习之路

掘金首页

[题目链接]

题目链接

[github地址]

github地址

[题目描述]

给你一个长度为 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<=1051 <= nums.length <= 10^5
  • 109<=nums[i]<=109-10^9 <= nums[i] <= 10^9
  • 答案保证符合 32-bit 整数

思路一:转换

  • 首先我们可以讲题目转换
  • 目标是使所有元素相等
  • 所以我们可以理解为将其中一个元素-1,这样同样是改变了所有元素的相对大小
  • 所以我们计算的是将所有元素减小到最小值的操作次数
  • i=0n1nums[i]min(nums)n\sum_{i=0}^{n-1}nums[i] - min(nums)*n
public int minMoves(int[] nums) {
    int minNum = Arrays.stream(nums).min().getAsInt();
    int res = 0;
    for (int num : nums) {
        res += num - minNum;
    }
    return res;
}
  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(1)O(1)

思路二:贪心法

  • 我们正常可以发现我们所求的res=(tnsum)/(n1)res=(t*n-sum)/(n-1)
  • t表示目标值,sum表示当前和
  • t >= max
  • 我们可以通过反证法证明每次最小值都会参与到操作数中
  • 假设不参与,那么最后的t一定会比当前t小,所以我们可以证明最小值一定参与
  • 同时最小值与其他数值的关系不会发生改变
  • 最后求解公式与思路1差不多
  • ans=sum−min*n
public int minMoves(int[] nums) {
        int n = nums.length;
        long min = nums[0], sum = 0;
        for (int i : nums) {
            min = Math.min(min, i);
            sum += i;
        }
        return (int)(sum - min * n);
    }
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)