贪心算法二--将数组和减半的最少操作次数

题目链接

一、问题定位

给定正整数数组 nums,每次操作选择当前数组最大元素 并将其减半(支持浮点数),目标是让数组总和减少至少一半 ,求完成目标的最少操作次数


二、核心算法:贪心策略 + 大根堆(最大堆)

  1. 贪心策略逻辑

    要让总和最快减少,每次必须选择当前最大的元素进行减半。因为最大元素的减半对总和的"减幅"最大,能以最少步骤达成目标。

  2. 大根堆的作用

    大根堆可以高效维护当前数组的最大值,支持 O(log n) 时间复杂度的"取出最大值"和"插入更新后的值"操作,保障算法效率。


三、解题步骤

  1. 计算初始总和

    先求出数组所有元素的和 total,目标是让总和减少量 ≥ total / 2(即剩余总和 ≤ total / 2)。

  2. 构建大根堆

    将数组元素存入大根堆,以便快速获取当前最大值。

  3. 迭代执行减半操作

    • 取出堆顶(当前最大值),计算其减半后的值。
    • 将减半后的值重新插入堆中。
    • 累加本次操作的"减少量"(原最大值 - 减半后的值),并记录操作次数。
    • 当累计减少量 ≥ total / 2 时,停止操作并返回次数。

四、正确性证明:交换论证法

  1. 核心思路

    通过"交换操作步骤",证明贪心解与最优解的等价性,从而验证贪心策略的最优性。

  2. 论证逻辑

    • 假设存在一个最优解 OPT,其操作顺序与贪心解 GREEDY 不同。
    • 找到第一个不同的操作位置:OPT 处理了较小元素 y,而 GREEDY 处理了较大元素 xx > 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,与示例输出一致。

相关推荐
只是懒得想了3 小时前
C++实现密码破解工具:从MD5暴力破解到现代哈希安全实践
c++·算法·安全·哈希算法
m0_736919103 小时前
模板编译期图算法
开发语言·c++·算法
dyyx1113 小时前
基于C++的操作系统开发
开发语言·c++·算法
m0_736919104 小时前
C++安全编程指南
开发语言·c++·算法
蜡笔小马4 小时前
11.空间索引的艺术:Boost.Geometry R树实战解析
算法·r-tree
-Try hard-4 小时前
数据结构:链表常见的操作方法!!
数据结构·算法·链表·vim
2301_790300964 小时前
C++符号混淆技术
开发语言·c++·算法
我是咸鱼不闲呀4 小时前
力扣Hot100系列16(Java)——[堆]总结()
java·算法·leetcode
嵌入小生0074 小时前
单向链表的常用操作方法---嵌入式入门---Linux
linux·开发语言·数据结构·算法·链表·嵌入式
LabVIEW开发4 小时前
LabVIEW金属圆盘压缩特性仿真
算法·labview·labview知识·labview功能·labview程序