堆结构实现石头粉碎算法及其工程应用

发布时间:2026/9/12 17:03:58

堆结构实现石头粉碎算法及其工程应用 1. 问题背景与核心思路这个问题源自经典的算法面试题有一堆石头每块石头的重量都是正整数。每次从中选出两块最重的石头进行粉碎如果重量相同则完全消失否则剩下两块石头重量之差的绝对值。重复这个过程直到只剩一块石头或没有石头返回最后剩下的石头重量。这个场景在实际工程中有多种应用场景比如负载均衡中服务器的动态权重调整游戏开发中道具合成系统的实现资源调度中的任务优先级处理2. 数据结构选型分析2.1 为什么选择堆结构堆优先队列是这个问题的理想选择原因在于每次操作都需要获取当前最大的两个元素插入新元素后需要保持有序性时间复杂度要求高效O(log n)的插入和删除相比其他数据结构数组排序每次操作后需要重新排序O(n log n)时间复杂度链表查找最大元素需要O(n)时间平衡二叉搜索树实现复杂杀鸡用牛刀2.2 C中的堆实现选择C标准库提供了几种优先队列实现方式// 方式1使用priority_queue最简洁 priority_queueint max_heap; // 方式2使用make_heap系列函数更灵活 vectorint heap; make_heap(heap.begin(), heap.end()); // 方式3使用multiset支持重复元素 multisetint, greaterint sorted_set;推荐使用priority_queue因为接口简洁明了底层默认使用vector实现效率有保障不需要手动维护堆属性3. 完整算法实现3.1 基础版本实现#include queue #include vector using namespace std; int lastStoneWeight(vectorint stones) { priority_queueint heap(stones.begin(), stones.end()); while (heap.size() 1) { int y heap.top(); heap.pop(); int x heap.top(); heap.pop(); if (y x) { heap.push(y - x); } // 相等时两者都消失不做操作 } return heap.empty() ? 0 : heap.top(); }3.2 优化版本实现针对可能的问题进行优化int lastStoneWeightOptimized(vectorint stones) { // 提前处理边界情况 if (stones.empty()) return 0; if (stones.size() 1) return stones[0]; // 使用移动语义避免拷贝 priority_queueint heap; for (int stone : stones) { heap.push(std::move(stone)); } while (heap.size() 1) { int y heap.top(); heap.pop(); int x heap.top(); heap.pop(); int diff y - x; if (diff 0) { // 减少不必要的push操作 if (!heap.empty() diff heap.top()) { // 如果新石头不是最大的可以先处理更大的 heap.push(diff); } else { // 否则可以直接处理 y diff; heap.push(y); continue; } } } return heap.empty() ? 0 : heap.top(); }4. 复杂度分析与性能考量4.1 时间复杂度设初始石头数量为n建堆O(n)每次操作2次pop(O(log n)) 可能的1次push(O(log n))最坏情况下需要n-1次操作总复杂度O(n log n)4.2 空间复杂度额外空间O(n)用于存储堆可以原地建堆优化到O(1)但会破坏输入数据4.3 性能优化技巧批量操作当剩余石头较多时可以一次性处理多个碰撞提前终止当堆顶元素为0时可以提前结束内存预分配预先reserve足够空间避免vector扩容并行处理对于大规模数据可以考虑并行建堆5. 边界条件与异常处理5.1 常见边界情况空输入应返回0单元素输入直接返回该元素所有石头重量相同应返回0大数情况注意整数溢出问题5.2 防御性编程实践int lastStoneWeightSafe(const vectorint stones) { try { // 验证输入数据 if (stones.size() 10000) { throw std::invalid_argument(Input too large); } for (int weight : stones) { if (weight 0) { throw std::invalid_argument(All weights must be positive); } } // 实际处理逻辑 return lastStoneWeightOptimized(stones); } catch (const std::exception e) { cerr Error: e.what() endl; return -1; // 或用optional/expected等更好 } }6. 实际应用扩展6.1 游戏开发中的应用在RPG游戏中可以用来实现class ItemMerger { public: void addItem(int weight) { inventory_.push(weight); } int mergeItems() { while (inventory_.size() 1) { int a inventory_.top(); inventory_.pop(); int b inventory_.top(); inventory_.pop(); int result abs(a - b); if (result 0) { inventory_.push(result); onMergeSuccess(a, b, result); } else { onMergeDisappear(a, b); } } return inventory_.empty() ? 0 : inventory_.top(); } private: priority_queueint inventory_; void onMergeSuccess(int a, int b, int result) { // 播放合成音效 // 显示特效 } void onMergeDisappear(int a, int b) { // 播放消失特效 } };6.2 分布式系统中的变种在处理分布式任务时可以扩展为struct Task { int priority; string id; // 其他元数据 bool operator(const Task other) const { return priority other.priority; } }; class TaskScheduler { public: void addTask(Task task) { queue_.push(std::move(task)); } void processTasks() { while (queue_.size() 2) { Task t1 queue_.top(); queue_.pop(); Task t2 queue_.top(); queue_.pop(); int diff t1.priority - t2.priority; if (diff 0) { t1.priority diff; queue_.push(std::move(t1)); } // 相等时两个任务都完成 } } private: priority_queueTask queue_; };7. 测试用例设计7.1 基础测试用例void testLastStoneWeight() { assert(lastStoneWeight({2,7,4,1,8,1}) 1); assert(lastStoneWeight({1,1}) 0); assert(lastStoneWeight({1}) 1); assert(lastStoneWeight({}) 0); assert(lastStoneWeight({10,10,10,10}) 0); assert(lastStoneWeight({1,3,5,7,9}) 1); }7.2 性能测试用例void testPerformance() { const int N 1000000; vectorint largeInput(N, 1); largeInput.back() 2; auto start chrono::high_resolution_clock::now(); int result lastStoneWeightOptimized(largeInput); auto end chrono::high_resolution_clock::now(); cout Result: result endl; cout Time: chrono::duration_castchrono::milliseconds(end-start).count() ms endl; }8. 常见问题与调试技巧8.1 典型错误模式忘记处理相等情况导致石头数量计算错误堆的顺序搞反默认是大顶堆需要时记得用greater边界条件遗漏空输入或单元素输入整数溢出大数相减可能产生负数8.2 调试技巧打印堆状态void printHeap(priority_queueint heap) { while (!heap.empty()) { cout heap.top() ; heap.pop(); } cout endl; }使用调试器观察g -g stone.cpp -o stone gdb ./stone break lastStoneWeight watch heap.size()单元测试框架#define CATCH_CONFIG_MAIN #include catch.hpp TEST_CASE(Last stone weight) { REQUIRE(lastStoneWeight({2,7,4,1,8,1}) 1); // 更多测试用例... }9. 算法变种与扩展思考9.1 保留所有中间结果vectorint lastStoneWeightProcess(vectorint stones) { vectorint process; priority_queueint heap(stones.begin(), stones.end()); while (heap.size() 1) { int y heap.top(); heap.pop(); int x heap.top(); heap.pop(); int diff y - x; process.push_back(diff); if (diff 0) { heap.push(diff); } } if (!heap.empty()) { process.push_back(heap.top()); } return process; }9.2 限制粉碎次数int lastStoneWeightWithLimit(vectorint stones, int k) { priority_queueint heap(stones.begin(), stones.end()); while (heap.size() 1 k-- 0) { int y heap.top(); heap.pop(); int x heap.top(); heap.pop(); if (y x) { heap.push(y - x); } } // 收集剩余所有石头 int total 0; while (!heap.empty()) { total heap.top(); heap.pop(); } return total; }9.3 多堆协作版本class MultiHeapSolution { public: void addPile(const vectorint stones) { heaps_.emplace_back(stones.begin(), stones.end()); } int compute() { // 找出所有堆顶最大的两个堆 // 处理它们的顶部元素 // 重复直到所有堆都处理完 // 实现略... } private: vectorpriority_queueint heaps_; };10. 工程实践建议API设计namespace StoneAlgorithm { int computeLastStoneWeight(spanconst int stones); int computeWithCustomComparator(spanconst int stones, functionbool(int,int) cmp); vectorint computeProcessSteps(spanconst int stones); }内存管理对于超大输入考虑使用内存映射文件可以使用自定义分配器优化priority_queue的内存使用并发处理int parallelLastStoneWeight(const vectorint stones) { // 将输入数据分片 // 每个线程处理一个子集 // 合并部分结果 // 最终处理剩余部分 }性能关键代码的优化// 使用更快的堆实现 #include boost/heap/fibonacci_heap.hpp int lastStoneWeightBoost(const vectorint stones) { boost::heap::fibonacci_heapint heap; for (int stone : stones) { heap.push(stone); } // 其余处理类似... }
延伸阅读

更多相关文章

2026/9/13 3:11:27

情感聊天机器人:大模型技术实现与商业应用

1. 情感聊天机器人的场景价值与技术适配性 情感聊天机器人作为大模型应用的切入点,其核心价值在于它完美匹配了大模型的技术特性与人类情感需求。从技术角度看,大模型的自然语言处理能力、上下文理解能力和生成多样性,恰好满足了情感交流所需…

2026/9/11 2:14:42

qmcdump:高效解码QQ音乐加密格式的完整实战指南

qmcdump:高效解码QQ音乐加密格式的完整实战指南 【免费下载链接】qmcdump 一个简单的QQ音乐解码(qmcflac/qmc0/qmc3 转 flac/mp3),仅为个人学习参考用。 项目地址: https://gitcode.com/gh_mirrors/qm/qmcdump qmcdump是一…

2026/9/11 2:16:44

意义悬置:符号闭环中的确定性替代-龍德明宇

意义悬置:符号闭环中的确定性替代 作者:龍德明宇[负主体性之顶刊论文系列六] 本文基于论文:Farquhar, S., Kossen, J., Kuhn, L., & Gal, Y. (2024). Detecting hallucinations in large language models using semantic entropy. Nature…

2026/9/13 11:42:35

LPC1778串口UART2调试教程:从寄存器配置到CH340驱动排障

简介:基于ARM Cortex-M3内核的LPC1778开发板资料包,面向嵌入式工程师、电子爱好者及高校学生,适合学习LPC1778芯片驱动开发、外设配置与Cortex-M3编程。压缩包内含887个文件,约76.56MB,以C源码(356个.c、31…

2026/9/13 11:42:35

AI工具矩阵如何助力小微企业降本增效

1. 项目背景:当AI工具遇上小微企业运营去年接手一家本地生活类自媒体账号时,我面临一个典型的小微企业困境:内容产出需求量大(每周需要15篇图文5条视频),但预算极其有限。按照行业标准,这样规模…

2026/9/13 11:42:35

消费电子ESD整改实战:三层防御体系设计与落地

1. 从“啪”一声到整机黑屏:这副耳机的ESD问题不是偶然,是设计链上的系统性失守你有没有过这样的经历——刚摘下耳机,手指碰到金属耳罩边缘,“啪”地一声脆响,手心一麻;下一秒,耳机RGB灯带突然熄…

2026/9/13 11:42:35

模糊小波神经网络在机器人实时威胁评估中的工程实现

简介:本资源是面向智能控制与机器人竞赛领域的工程实践项目,聚焦模糊小波神经网络(FWNN)在目标威胁评估中的Matlab实现,特别适配RoboMaster等实时对抗类机器人系统的攻击优先级决策需求。资源提供完整可运行的算法框架…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/13 0:01:16

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/12 6:29:36

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/12 14:32:17

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/13 11:18:28

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码