当前位置: 首页 > news >正文

LeetCode 3296. 移山所需的最少秒数 技术解析(含完整可运行代码)

摘要:本文针对LeetCode 3296题“移山所需的最少秒数”,从问题本质出发,拆解题意、分析核心痛点,推导最优解题思路(二分查找),详细讲解算法原理、边界处理及代码实现细节,结合示例验证算法正确性,同时分析时间复杂度与空间复杂度,给出优化方向,帮助开发者快速理解并掌握该题的解题逻辑,适配面试、算法练习等场景。

一、问题核心解析

1.1 题目题意拆解

题目核心需求:给定山的高度mountainHeight和工人们的工作时间数组workerTimes,工人们同时工作,将山的高度降至0,求最少所需秒数。

关键规则(重点理解):

  • 工人i降低山的高度x,所需时间为workerTimes[i] * (1 + 2 + ... + x) = workerTimes[i] * x*(x+1)/2(等差数列求和公式,核心推导点);

  • 所有工人同时工作,总耗时取所有工人各自耗时的最大值(因为需等耗时最长的工人完成,整体才算结束);

  • 目标:分配每个工人需要降低的高度(所有工人降低的高度总和 ≥ mountainHeight),使得所有工人的耗时最大值最小化。

1.2 核心痛点与解题关键

痛点1:直接暴力分配高度(枚举所有可能的分配方式),时间复杂度极高,无法适配mountainHeight(≤1e5)和workerTimes长度(≤1e4)的约束;

痛点2:工人耗时与降低高度呈二次函数关系(x*(x+1)/2),分配高度时需平衡各工人的耗时,避免单个工人耗时过高;

解题关键:二分查找。将“求最少耗时”转化为“判断某一耗时T是否能完成移山”,通过二分枚举T的可能值,找到最小的满足条件的T。

二、解题思路推导(二分查找核心逻辑)

2.1 二分查找的可行性分析

二分查找的前提是“单调性”,本题满足单调性:

  • 若耗时T能完成移山,则所有大于T的耗时也一定能完成(只需减少部分工人的降低高度,总耗时不会增加);

  • 若耗时T不能完成移山,则所有小于T的耗时也一定不能完成(时间不足,无法让所有工人完成足够的高度降低)。

2.2 二分查找的边界确定

确定二分查找的左边界left和右边界right,缩小枚举范围:

  1. 左边界left:最小可能耗时,初始为0(理论上的最小值,实际需满足至少能完成移山);

  2. 右边界right:最大可能耗时,即“单个工人完成所有移山工作”的耗时(最坏情况,只有一个工人),计算公式为workerTimes[max_idx] * mountainHeight*(mountainHeight+1)/2(max_idx为workerTimes中最大值的索引)。

2.3 核心判断函数(check函数)

对于给定的耗时T,判断所有工人在T时间内,最多能共同降低的山的高度总和是否 ≥ mountainHeight。

关键推导(单个工人的最大降低高度):

设工人i在时间T内最多能降低x高度,则满足workerTimes[i] * x*(x+1)/2 ≤ T

变形可得:x² + x - 2*T/workerTimes[i] ≤ 0

解这个一元二次方程,取正根的整数部分(因为x必须是正整数),即x = floor( (sqrt(1 + 8*T/workerTimes[i]) - 1) / 2 )

遍历所有工人,计算每个工人的最大降低高度x,求和后与mountainHeight比较:若总和 ≥ mountainHeight,则T可行;否则不可行。

2.4 二分查找完整流程

  1. 初始化left=0,right=单个工人完成所有工作的最大耗时;

  2. 当left < right时,计算mid = (left + right) // 2;

  3. 调用check(mid),判断mid时间是否能完成移山:

    • 若能完成,说明mid可能是最优解,缩小右边界:right = mid;

    • 若不能完成,说明时间不足,扩大左边界:left = mid + 1;

  4. 循环结束后,left(或right)即为最少所需秒数。

三、算法实现(Python,贴合要求格式)

核心代码严格遵循题目要求的Solution类格式,包含完整的check函数、二分查找逻辑,注释详细,可直接复制运行,适配LeetCode提交规范。

importmathclassSolution:defminNumberOfSeconds(self,mountainHeight:int,workerTimes:list[int])->int:""" 计算移山所需的最少秒数 :param mountainHeight: 山的初始高度 :param workerTimes: 工人们的工作时间数组,workerTimes[i]表示工人i每单位高度的基础耗时 :return: 最少所需秒数 """defcheck(T:int)->bool:""" 判断在耗时T内,所有工人能否共同将山的高度降至0 :param T: 给定的耗时 :return: 能完成返回True,否则返回False """total=0# 所有工人在T时间内最多能降低的总高度fortinworkerTimes:# 推导单个工人在T时间内最多能降低的高度x# 由 t * x*(x+1)/2 ≤ T → x² + x - 2*T/t ≤ 0# 解一元二次方程,取正根的整数部分discriminant=1+8*T//t# 判别式,避免浮点数误差,先整除x=(math.isqrt(discriminant)-1)//2total+=x# 剪枝:总高度已满足,无需继续计算其他工人iftotal>=mountainHeight:returnTruereturntotal>=mountainHeight# 确定二分查找的边界# 右边界:单个工人完成所有工作的最大耗时(最坏情况)max_time=max(workerTimes)right=max_time*mountainHeight*(mountainHeight+1)//2left=0# 二分查找核心逻辑whileleft<right:mid=(left+right)//2ifcheck(mid):# 耗时mid可行,尝试更小的耗时right=midelse:# 耗时mid不可行,需要更大的耗时left=mid+1returnleft

四、代码细节解析与优化

4.1 关键细节说明

  1. 判别式计算优化:使用8 * T // t而非8 * T / t,避免浮点数精度误差,确保后续开方计算的准确性;

  2. 开方函数选择:使用math.isqrt(Python 3.8+),用于计算非负整数的整数平方根,比math.sqrt更高效,且避免浮点数转换;

  3. 剪枝操作:在check函数中,当累计总高度≥mountainHeight时,立即返回True,无需遍历所有工人,提升效率;

  4. 边界处理:right的计算采用整数运算,避免溢出(Python无整数溢出问题,但保持规范,适配其他语言迁移)。

4.2 时间复杂度与空间复杂度分析

  • 时间复杂度:O(n * logM),其中n为workerTimes的长度(≤1e4),M为二分查找的边界范围(最大为1e6 * 1e5 * 1e5 = 1e16,log2(1e16)≈53)。整体计算量约为1e4 * 53 = 5.3e5,完全满足题目约束;

  • 空间复杂度:O(1),仅使用常数级变量,无额外空间开销。

4.3 可能的优化方向

针对极端场景(如workerTimes中存在大量重复值),可先对workerTimes进行去重,减少check函数中的遍历次数,进一步提升效率;但在常规场景下,原代码已足够高效,无需额外优化。

五、示例验证(贴合题目示例,验证算法正确性)

示例1:输入mountainHeight=4,workerTimes=[2,1,1]

二分查找过程简述:

  • right = max([2,1,1]) * 45//2 = 220//2 = 20,left=0;

  • mid=(0+20)//2=10,check(10):工人0可降x=(sqrt(1+8*10/2)-1)/2=3,工人1可降x=4,工人2可降x=4,总高度3+4+4=11≥4,可行,right=10;

  • 持续二分,最终收敛到left=right=3,与示例输出一致。

示例2:输入mountainHeight=10,workerTimes=[3,2,2,4]

验证:当T=12时,check(12):

  • 工人0(t=3):x=(sqrt(1+812/3)-1)/2=(sqrt(33)-1)/2≈2,耗时32*3//2=9≤12;

  • 工人1(t=2):x=(sqrt(1+812/2)-1)/2=(sqrt(49)-1)/2=3,耗时23*4//2=12≤12;

  • 工人2(t=2):同工人1,x=3;

  • 工人3(t=4):x=(sqrt(1+812/4)-1)/2=(sqrt(25)-1)/2=2,耗时42*3//2=12≤12;

  • 总高度2+3+3+2=10≥10,可行,且无更小的T满足条件,输出12,与示例一致。

示例3:输入mountainHeight=5,workerTimes=[1]

验证:right=156//2=15,二分查找最终收敛到15,与示例输出一致。

六、常见错误与注意事项

  • 错误1:忽略“工人同时工作,总耗时取最大值”的规则,误将所有工人耗时求和作为总耗时;

  • 错误2:推导单个工人最大降低高度时,未使用等差数列求和公式,导致公式错误(如写成tx而非tx*(x+1)/2);

  • 错误3:二分查找边界设置过小,导致无法找到可行解(如right未取单个工人的最大耗时);

  • 错误4:使用浮点数开方后未取整,导致x计算错误(如未用floor或整数除法)。

七、总结

本题的核心是将“最小化最大耗时”的优化问题,通过二分查找转化为“可行性判断”的问题,核心难点在于理解工人耗时与降低高度的二次关系,并推导单个工人最大降低高度的计算公式。

本文实现的代码严格遵循题目要求,逻辑严谨、细节优化到位,可直接提交LeetCode通过所有测试用例。同时,二分查找的思路可迁移到类似“最小化最大成本”“最大化最小收益”的优化问题中,具有较强的通用性。

对于初学者,建议重点掌握“二分查找+可行性判断”的解题框架,理解check函数的推导过程,明确二分边界的确定方法,逐步提升对优化类算法的解题能力。

http://www.jsqmd.com/news/474290/

相关文章:

  • 2026新建公路路口哨兵高性价比供应商推荐:雷达测速仪安装、雷达测速仪生产厂家、固定式雷达测速仪、平安路口弯道哨兵选择指南 - 优质品牌商家
  • HFSS建模仿真实战:从基础设置到T形波导优化
  • Nunchaku-flux-1-dev辅助Agent系统开发:任务规划与执行
  • 线性方程组迭代解法实战:雅可比、Gauss-Seidel与SOR算法的MATLAB实现与性能对比
  • 低显存也能玩Qwen-Image-Layered?优化配置让24G显卡流畅运行
  • 因子图 vs 图优化:傻傻分不清?本文彻底讲透两者的本质区别
  • 运营同学不用愁了!输入 URL 几分钟搞定专业宣传视频
  • GLM-OCR开源模型部署详解:对比传统软件安装的优势
  • Qt开源背后的那些秘密
  • 立创EDA模块化桌面时钟:基于M.2核心板与PCI-E 1x扩展板的硬件架构与实现
  • Phi-3 Forest Laboratory作品集:3.8B参数模型在数学证明与编程题解中表现
  • RVC模型参数详解与调优指南:如何获得最佳变声效果
  • 3个颠覆性突破的AI图像分层效率革命
  • 怀旧游戏复活指南:用《星尘传说》源码5步搭建私人服务器(含22职业平衡调整技巧)
  • Youtu-VL-4B-Instruct企业应用:金融财报图表自动分析与趋势解读案例
  • 解决Windows运行库难题:vcredist全攻略
  • CodeFormer:基于代码本查找Transformer的AI人脸修复技术全解析
  • 告别VIP音频离线烦恼:xmly-downloader-qt5让你轻松实现本地永久保存
  • 锂电池SOC估计:从算法到代码实践
  • 探索 36G1 - 改进 critic - TOPSIS 算法及仿真实现
  • Kimi-VL-A3B-Thinking效果实测:模糊/低光照/旋转倾斜图片的鲁棒性识别能力
  • Fish-Speech-1.5实现多语言客服机器人:基于Vue的前端交互设计
  • 解决老游戏兼容性难题:DDrawCompat的焕新方案
  • 让前厅更高效,让服务更暖心——HWT2.0酒店话务台,重构宾客体验新范式
  • Phi-4-mini-reasoning推理效果展示|ollama生成博士级数学综述摘要
  • 基于Web技术的Local Moondream2浏览器端部署方案
  • MySQL 批量删除海量数据的几种方法
  • Phi-3-mini-128k-instructGPU算力优化:vLLM量化配置(AWQ/GPTQ)实测效果对比
  • Qwen3-Reranker-0.6B一键部署教程:5分钟搭建本地语义重排序服务
  • 采样延迟从800ms压至23ms,MCP Sampling调用流优化全链路剖析,含4类必踩坑清单