一、问题定位
给定正整数数组 nums,每次操作选择当前数组最大元素 并将其减半(支持浮点数),目标是让数组总和减少至少一半 ,求完成目标的最少操作次数。
二、核心算法:贪心策略 + 大根堆(最大堆)
-
贪心策略逻辑
要让总和最快减少,每次必须选择当前最大的元素进行减半。因为最大元素的减半对总和的"减幅"最大,能以最少步骤达成目标。
-
大根堆的作用
大根堆可以高效维护当前数组的最大值,支持
O(log n)时间复杂度的"取出最大值"和"插入更新后的值"操作,保障算法效率。
三、解题步骤
-
计算初始总和
先求出数组所有元素的和
total,目标是让总和减少量 ≥total / 2(即剩余总和 ≤total / 2)。 -
构建大根堆
将数组元素存入大根堆,以便快速获取当前最大值。
-
迭代执行减半操作
- 取出堆顶(当前最大值),计算其减半后的值。
- 将减半后的值重新插入堆中。
- 累加本次操作的"减少量"(原最大值 - 减半后的值),并记录操作次数。
- 当累计减少量 ≥
total / 2时,停止操作并返回次数。
四、正确性证明:交换论证法
-
核心思路
通过"交换操作步骤",证明贪心解与最优解的等价性,从而验证贪心策略的最优性。
-
论证逻辑
- 假设存在一个最优解
OPT,其操作顺序与贪心解GREEDY不同。 - 找到第一个不同的操作位置:
OPT处理了较小元素y,而GREEDY处理了较大元素x(x > y)。 - 将
OPT中这次处理y的操作替换为处理x,可证明新解仍满足条件且操作次数不增加。 - 重复交换,最终可将
OPT转化为GREEDY,说明贪心解是最优的。
- 假设存在一个最优解
五、示例验证(图中案例)
输入:nums = [5,19,8,1]
初始总和:5+19+8+1 = 33,目标减少量:33/2 = 16.5
- 第1次操作:19 → 9.5,减少量
9.5(累计:9.5) - 第2次操作:9.5 → 4.75,减少量
4.75(累计:14.25) - 第3次操作:8 → 4,减少量
4(累计:18.25 ≥ 16.5)
最终操作次数为3,与示例输出一致。
