力扣 1046 :以大顶堆破石碰之题,悟数据结构知行合一之道

📅 2026/7/19 21:16:04
力扣 1046 :以大顶堆破石碰之题,悟数据结构知行合一之道
力扣 1046 以大顶堆破石碰之题悟数据结构知行合一之道前言一、题意详细拆解二、算法选型论证 文本图形原理演示2.1 方案对比暴力遍历 VS 大顶堆优化2.2 大顶堆结构 ASCII 图文示意2.3 石块碰撞分步流程图解步骤 1取出 max8、次 max7差值 1新石入堆步骤 2取出 max4、次 max2差值 2新石入堆步骤 3取出 max2、次 max1差值 1新石入堆步骤 4取出 max1、次 max1重量相等直接销毁三、C 完整代码实现带详细注释四、性能深度分析五、算法学习思辨数据结构理论与落地的思维转化六、文末总结标签#C #数据结构 #大顶堆 #算法解题 #优先队列摘要本文依托石块碰撞经典算法例题由题意拆解、原理图解、代码落地、性能对比到学习方法论逐层展开详解大顶堆的实战用法兼顾底层原理与上层编程思维理清数据结构从理论到落地的思维转变逻辑。前言夫算法者驭离散数据之章法解繁杂业务之良方。堆依托完全二叉树而生藏动态极值调度之玄机碎石碰撞一题看似零散无序实则为大顶堆的经典试炼。穷究底层实现可溯源源码内核活用封装接口可速写落地代码。学结构而不知活用如握利剑空悬鞘会调用而不明本源似筑楼阁缺地基。本文从例题入手分步拆解解题逻辑附原理图文、C 实操代码与性能对比兼论数据结构的科学学习思路。一、题意详细拆解给定一组正整数代表不同石块重量持续循环执行碰撞规则直至集合剩余石块数量小于等于 1每一轮操作从全部石块里筛选重量最大、次大两块石料两石重量完全相等相撞粉碎两块石块直接消失无新石块生成两石重量大小不一碰撞抵消后诞生一块新石料新石重量 重石重量 − 轻石重量新石块重新放回原石集合。最终结果判定若石块全部湮灭无剩余返回数值0仅剩单块石料返回该石块的重量。经典样例初始石块数组[2,7,4,1,8,1]按照规则反复碰撞后最终剩余石块重量为1。二、算法选型论证 文本图形原理演示2.1 方案对比暴力遍历 VS 大顶堆优化暴力枚举方案依托普通数组存储数据每轮全数组遍历查找最大值、次大值。单次遍历耗时O ( n ) O(n)O(n)最多执行n nn轮循环整体时间复杂度b o l d s y m b o l O ( n 2 ) boldsymbol{O(n^2)}boldsymbolO(n2)数据量级过万时程序运行效率骤降大数据场景不可用大顶堆优化方案大顶堆天然满足堆顶永远存储当前集合最大值入堆、弹出堆顶元素操作耗时仅O ( l o g n ) O(logn)O(logn)整体算法复杂度b o l d s y m b o l O ( n l o g n ) boldsymbol{O(nlogn)}boldsymbolO(nlogn)十万级数据依旧运行流畅是本题最优解。综上选用 C STL 内置priority_queue默认原生大顶堆作为数据容器。2.2 大顶堆结构 ASCII 图文示意以样例[2,7,4,1,8,1]构建初始大顶堆文本绘制堆树形结构8 ←堆顶(全局最大值) / \ 7 4 / / \ 2 1 1结构说明大顶堆是完全二叉树任意父节点数值大于左右子节点保证堆顶时刻为集合极值是动态取最大值的最优结构。2.3 石块碰撞分步流程图解初始堆集合{8,7,4,2,1,1}步骤 1取出 max8、次 max7差值 1新石入堆新堆集合{4,2,1,1,1}4 / \ 2 1 / \ 1 1步骤 2取出 max4、次 max2差值 2新石入堆新堆集合{2,1,1,1}2 / \ 1 1 / 1步骤 3取出 max2、次 max1差值 1新石入堆新堆集合{1,1,1}步骤 4取出 max1、次 max1重量相等直接销毁新堆集合{1}堆内仅剩单个元素算法终止返回结果1。三、C 完整代码实现带详细注释C 标准库中priority_queueint默认基于大顶堆实现无需手动改造堆结构直接导入容器即可快速编码#includeiostream#includevector#includequeueusingnamespacestd;/** * brief 计算碰撞后剩余石块重量 * param stones 存储所有石块重量的数组 * return 最终剩余石块重量无剩余返回0 */intlastStoneWeight(vectorintstones){// 直接用数组初始化大顶堆STL优先队列默认大顶堆priority_queueintmaxHeap(stones.begin(),stones.end());// 堆内石块多于1块时持续碰撞循环while(maxHeap.size()1){// 取出当前最大值intheavymaxHeap.top();maxHeap.pop();// 取出当前次大值intlightmaxHeap.top();maxHeap.pop();// 重量不等生成差值新石块放回堆中if(heavy!light){maxHeap.push(heavy-light);}// 重量相等石块直接销毁不做入堆操作}// 堆空返回0存有数据返回堆顶数值returnmaxHeap.empty()?0:maxHeap.top();}// 测试入口intmain(){vectorinttestStones{2,7,4,1,8,1};cout剩余石块重量lastStoneWeight(testStones)endl;return0;}运行输出剩余石块重量1四、性能深度分析实现方案时间复杂度适用场景短板数组暴力遍历O ( n 2 ) O(n^2)O(n2)数据量 n100 小规模测试海量数据循环超时STL 大顶堆O ( n l o g n ) O(nlogn)O(nlogn)海量随机数据、工业级业务场景需理解堆特性入门稍有门槛补充自建数组实现手写大顶堆复杂度同样为O ( n l o g n ) O(nlogn)O(nlogn)适合底层原理学习工程开发优先使用 STL 优先队列降低编码成本。五、算法学习思辨数据结构理论与落地的思维转化夯基固本方可行稳致远学以致用才算吃透结构。研习堆这类数据结构历来分底层深耕与上层落地两层修为二者缺一不可其一深挖底层本源吃透堆依托数组存储、完全二叉树排布、上浮下沉调整节点的底层逻辑。通晓实现细节日后研读开源框架源码、容器底层实现时能够看透堆排序、优先队列的内核原理不因封装而茫然无措其二简化上层建模实战解题之时抛开树形结构、数组存储等底层细节仅将优先队列抽象为可以动态存取最值的特殊集合。只关注「插入元素、取出最大值」两个核心功能剥离无关细节快速建立解题模型。学界常有两类学习者之弊一类死磕底层原理做题拘泥于数据结构实现细节无法灵活转化思路一类只会调用库函数 API不明底层逻辑面对源码阅读、手写数据结构题型束手无策。深耕原理筑牢根基简化思维灵活落地方是修习算法的中正之道。就本题而言解题全程不必思虑堆是树还是数组只依托「集合动态取极值」的需求选用大顶堆便是思维转化的直观体现。六、文末总结堆藏二叉树之数理例题显编程之实用。深挖底层以固学识之本活用封装以提编码之速。一块碎石碰撞小题窥破数据结构从书本理论到代码落地的转化法门。但凡后续遇见动态筛选极值类算法场景优先从堆结构入手分析便是破题捷径。格物致知由题悟理循序渐进算法功力自然日有所进。