题目描述
思路解析动画文字版
思路浓缩成一句:反复取最大、动态加入 → 大顶堆(优先队列)。先把 6 块石头逐个插堆(上浮),再开始对撞。
插入石头 2。
堆里只有它一个,自然就是堆顶。
插入石头 7。
子节点 7 比父节点 2 大,违反大顶堆,交换二者让大的往上走。
7 浮到了堆顶,成为当前最重的石头。
插入石头 4。
比较 4 和它的父节点 7:父更大(或相等),大顶堆性质已满足,停止上浮。
插入石头 1。
比较 1 和它的父节点 2:父更大(或相等),大顶堆性质已满足,停止上浮。
插入石头 8。
子节点 8 比父节点 2 大,违反大顶堆,交换二者让大的往上走。
子节点 8 比父节点 7 大,违反大顶堆,交换二者让大的往上走。
8 浮到了堆顶,成为当前最重的石头。
插入石头 1。
比较 1 和它的父节点 4:父更大(或相等),大顶堆性质已满足,停止上浮。
六块石头都进堆了,堆顶是最重的 8。大顶堆建好,开始对撞。
取出堆顶 8——它就是当前最重的石头。
把末尾的石头 1 临时补到堆顶占位,接下来让它下沉到合适位置。
堆顶 1 比孩子 7 小,交换:把更大的孩子换上来,最大值重新坐回堆顶。
堆顶 1 比孩子 2 小,交换:把更大的孩子换上来,最大值重新坐回堆顶。
堆顶 7 已不小于它的孩子,大顶堆恢复,下沉结束。
取出堆顶 7——它就是当前最重的石头。
把末尾的石头 1 临时补到堆顶占位,接下来让它下沉到合适位置。
堆顶 1 比孩子 4 小,交换:把更大的孩子换上来,最大值重新坐回堆顶。
堆顶 4 已不小于它的孩子,大顶堆恢复,下沉结束。
两块最重的石头 8 和 7 相撞:8 − 7 = 1,碎出一块 1 的新石头,放回堆里。
把对撞产生的石头 1 放回堆末尾,再上浮归位。
比较 1 和它的父节点 2:父更大(或相等),大顶堆性质已满足,停止上浮。
取出堆顶 4——它就是当前最重的石头。
把末尾的石头 1 临时补到堆顶占位,接下来让它下沉到合适位置。
堆顶 1 比孩子 2 小,交换:把更大的孩子换上来,最大值重新坐回堆顶。
堆顶 2 已不小于它的孩子,大顶堆恢复,下沉结束。
取出堆顶 2——它就是当前最重的石头。
把末尾的石头 1 临时补到堆顶占位,接下来让它下沉到合适位置。
堆顶 1 已不小于它的孩子,大顶堆恢复,下沉结束。
两块最重的石头 4 和 2 相撞:4 − 2 = 2,碎出一块 2 的新石头,放回堆里。
把对撞产生的石头 2 放回堆末尾,再上浮归位。
子节点 2 比父节点 1 大,违反大顶堆,交换二者让大的往上走。
子节点 2 比父节点 1 大,违反大顶堆,交换二者让大的往上走。
2 浮到了堆顶,成为当前最重的石头。
取出堆顶 2——它就是当前最重的石头。
把末尾的石头 1 临时补到堆顶占位,接下来让它下沉到合适位置。
堆顶 1 已不小于它的孩子,大顶堆恢复,下沉结束。
取出堆顶 1——它就是当前最重的石头。
把末尾的石头 1 临时补到堆顶占位,接下来让它下沉到合适位置。
堆顶 1 已不小于它的孩子,大顶堆恢复,下沉结束。
两块最重的石头 2 和 1 相撞:2 − 1 = 1,碎出一块 1 的新石头,放回堆里。
把对撞产生的石头 1 放回堆末尾,再上浮归位。
比较 1 和它的父节点 1:父更大(或相等),大顶堆性质已满足,停止上浮。
取出堆顶 1——它就是当前最重的石头。
把末尾的石头 1 临时补到堆顶占位,接下来让它下沉到合适位置。
堆顶 1 已不小于它的孩子,大顶堆恢复,下沉结束。
取出堆顶 1——它就是当前最重的石头。
把末尾的石头 1 临时补到堆顶占位,接下来让它下沉到合适位置。
堆顶 1 已不小于它的孩子,大顶堆恢复,下沉结束。
两块石头一样重(1 和 1)相撞:两块都碎光,什么都不放回。
堆里只剩一块石头 1,再也凑不出两块来撞,它就是最后的答案。
几个边界自己心算一遍。
两个高频追问。
参考代码
import heapqdef lastStoneWeight(stones): h = [-s for s in stones] # 取负模拟大顶堆 heapq.heapify(h) while len(h) > 1: y = -heapq.heappop(h) # 最重 x = -heapq.heappop(h) # 次重 if y > x: heapq.heappush(h, -(y - x)) return -h[0] if h else 0复杂度
- 时间:O(n log n),最多 n 轮,每轮两次 pop + 一次 push,各 O(log n)
- 空间:O(n),堆里最多放 n 块石头
易错点
面试追问把动画讲成自己的话
追问Java 里怎么得到大顶堆?
追问这题能不能不用堆?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
最接近原点的 K 个点
LeetCode 973 · 中等 · 沿着 堆 / 优先队列 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题