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


文章目录

摘要

这道题乍一看有点反直觉。

题目说的是:

每次操作让 n - 1 个元素加 1

很多人第一反应是:

  • 模拟?
  • 暴力?
  • 反复加到一样?

但实际上,这道题一旦你 换一个视角,就会发现答案非常简单,甚至可以一行代码解决。

核心在于一句话:

"给 n - 1 个数加 1,本质上等价于给 1 个数减 1。"

只要想通这一点,这题基本就结束了。

描述

题目给你一个整数数组 nums,长度是 n

规则是:

  • 每次操作,可以让数组中 任意 n - 1 个元素加 1
  • 目标是让 所有元素最终相等
  • 问最少需要多少次操作

示例

text 复制代码
nums = [1,2,3]

可以这样操作:

text 复制代码
[1,2,3] -> [2,3,3] -> [3,4,3] -> [4,4,4]

答案是 3

题解答案(核心思路)

一句话核心结论

最小操作次数 = 所有元素与最小值的差之和

公式表示就是:

text 复制代码
sum(nums) - min(nums) * n

为什么可以这么算?

关键在于 等价变换

原操作:
  • 每次让 n - 1 个数 +1
等价理解:
  • 整个数组都 +1
  • 然后选 1 个数 -1

整体结果没变。

也就是说:

每次操作,相当于选择一个元素,让它 -1

问题就被简化成了什么?

变成了:

每次可以让某一个数减 1

要把所有数都变成同一个值(而且操作次数最少)

那目标值选谁最合理?

答案是:数组中的最小值

为什么目标是最小值?

  • 你只能"减",不能"加"
  • 把大的数减到最小值,代价最小
  • 如果选更小的值,反而要多做无意义的操作

题解答案(Swift 可运行 Demo)

swift 复制代码
class Solution {
    func minMoves(_ nums: [Int]) -> Int {
        guard let minValue = nums.min() else {
            return 0
        }
        
        var result = 0
        for num in nums {
            result += num - minValue
        }
        
        return result
    }
}

题解代码分析

1. 为什么先找最小值?

swift 复制代码
guard let minValue = nums.min() else {
    return 0
}

这是整个算法的"锚点"。

我们最终的目标是:

  • 所有元素 → minValue

2. 操作次数怎么累加?

swift 复制代码
result += num - minValue

含义非常直观:

  • 当前元素是 num
  • 目标是 minValue
  • 每减少 1,就相当于一次操作
  • 那需要 num - minValue

3. 为什么直接累加就行?

因为:

  • 每次操作,只影响一个"被减"的元素
  • 不同元素之间互不干扰
  • 总操作数就是每个元素单独的"减法次数"之和

示例测试及结果

示例 1

swift 复制代码
let solution = Solution()
print(solution.minMoves([1, 2, 3]))

输出:

text 复制代码
3

解释:

text 复制代码
(1 - 1) + (2 - 1) + (3 - 1) = 0 + 1 + 2 = 3

示例 2

swift 复制代码
print(solution.minMoves([1, 1, 1]))

输出:

text 复制代码
0

所有元素已经相等,不需要操作。

再举一个负数的例子

swift 复制代码
print(solution.minMoves([-1, 0, 2]))

计算过程:

text 复制代码
min = -1
(-1 - -1) + (0 - -1) + (2 - -1)
= 0 + 1 + 3
= 4

实际场景结合

这道题在真实开发中,其实很常见,比如:

1. 数据归一化

你有一组数:

  • 每次只能"整体提升"
  • 想让所有数据回到同一基准

这时就可以反向思考:

  • 谁是最低基准
  • 其他值要"补齐"多少

2. 资源平衡问题

比如:

  • 多个服务实例负载不均
  • 每次只能"给大多数实例加资源"

那从另一个角度看:

  • 是在"惩罚"负载最高的那个实例

3. 面试中的常见陷阱

这题非常适合考:

  • 是否能跳出题面
  • 是否具备等价转换能力
  • 是否能把复杂操作转成简单数学问题

时间复杂度

  • 找最小值:O(n)
  • 遍历求和:O(n)

总时间复杂度:

text 复制代码
O(n)

空间复杂度

  • 只使用了常量变量

空间复杂度:

text 复制代码
O(1)

总结

LeetCode 453 是一道非常典型的:

  • 看起来复杂
  • 实际一行公式就能解决
  • 极度考察"问题视角转换能力"的题

只要你记住这句话:

"给 n - 1 个数加 1,等价于给 1 个数减 1。"

这道题基本就是秒解。

相关推荐
踩坑记录21 小时前
leetcode hot100 3.无重复字符的最长子串 medium 滑动窗口(双指针)
python·leetcode
Z1Jxxx21 小时前
01序列01序列
开发语言·c++·算法
汽车仪器仪表相关领域1 天前
全自动化精准检测,赋能高效年检——NHD-6108全自动远、近光检测仪项目实战分享
大数据·人工智能·功能测试·算法·安全·自动化·压力测试
Doro再努力1 天前
【数据结构08】队列实现及练习
数据结构·算法
清铎1 天前
leetcode_day12_滑动窗口_《绝境求生》
python·算法·leetcode·动态规划
linweidong1 天前
嵌入式电机:如何在低速和高负载状态下保持FOC(Field-Oriented Control)算法的电流控制稳定?
stm32·单片机·算法
踩坑记录1 天前
leetcode hot100 42 接雨水 hard 双指针
leetcode
net3m331 天前
单片机屏幕多级菜单系统之当前屏幕号+屏幕菜单当前深度 机制
c语言·c++·算法
mmz12071 天前
二分查找(c++)
开发语言·c++·算法
Insight1 天前
拒绝手动 Copy!一文吃透 PyTorch/NumPy 中的广播机制 (Broadcasting)
算法