mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-21 19:06:11 +00:00
9135647d93
Add dedicated chapter exercise sections and generated exercise pages for the English, Japanese, and Russian editions. Add navigation for all published languages while keeping Taiwan Traditional Chinese exercise pages generated at build time.
3.9 KiB
3.9 KiB
练习
知识巩固
数字 10 入堆后怎样调整
数组 [9, 7, 8, 3, 5] 表示一个大顶堆。现在将数字 10 入堆。
- 先把 10 添加到数组末尾,它的父节点值是多少?
- 从新节点开始向上堆化,写出每次交换后的数组。
- 最终的堆顶元素是什么?一共交换了几次?
??? success "参考答案"
1. 10 添加后的索引为 5,其父节点索引为
$\lfloor(5-1)/2\rfloor=2$,父节点值为 8。
2. 10 大于 8,第一次交换后为 `[9, 7, 10, 3, 5, 8]`;
10 又大于父节点 9,第二次交换后为 `[10, 7, 9, 3, 5, 8]`。
此时 10 已到达根节点,堆化结束。
3. 最终堆顶为 10,共交换 2 次。
检查小顶堆的父子关系
数组 [1, 4, 3, 7, 6, 2] 表示一棵完全二叉树。小顶堆要求每个父节点都不大于它的孩子。
对索引 $i$,左、右孩子索引分别为 2i+1 和 $2i+2$。
- 索引 2 的孩子索引和值分别是什么?
- 索引 2 处的节点值为 3,它与孩子节点之间是否违反小顶堆规则?如果违反,应交换哪两个元素?
- 根据第 2 问的判断:若违反规则,写出交换后的数组;若不违反,说明无须交换。最后检查其余父子关系。
??? success "参考答案"
1. 索引 2 的左孩子索引是 5、值为 2;右孩子索引是 6,但数组长度为 6,因此右孩子不存在。
2. 父节点值 3 大于孩子值 2,违反小顶堆规则,应交换索引 2 和索引 5 的元素。
3. 交换后得到 `[1, 4, 2, 7, 6, 3]`。逐一检查:
`1 ≤ 4`、`1 ≤ 2`;`4 ≤ 7`、`4 ≤ 6`;`2 ≤ 3`。
所有父节点都不大于自己的孩子,因此现在满足小顶堆规则。
用小顶堆保留最大的三个数
要从数据流 [4, 1, 7, 3, 8] 中保留最大的 3 个数,可以维护一个大小不超过 3 的小顶堆。
先把前 3 个数依次放入小顶堆。堆满后,每读入一个新数: 如果它大于堆顶,就删除堆顶并放入新数;否则堆保持不变。
请写出每次读入数字后堆中保留的数字和堆顶。 只需把保留的数字写成集合,不要求写出它们在堆数组中的排列。
??? success "参考答案"
每次读入数字后的结果如下:
| 读入数字 | 保留的数字 | 堆顶 |
| --- | --- | --- |
| 4 | `{4}` | 4 |
| 1 | `{1, 4}` | 1 |
| 7 | `{1, 4, 7}` | 1 |
| 3 | `{3, 4, 7}` | 3 |
| 8 | `{4, 7, 8}` | 4 |
堆满后,堆顶是当前保留数字中最小的一个。只有新数字大于堆顶时,
才用新数字替换堆顶。最终保留的 `{4, 7, 8}` 正是最大的 3 个数。
编程练习
寻找数组中的第 k 大元素
给定整数数组 nums 和整数 $k$,其中 $1 \le k \le n$,n 是数组长度。把数组按从大到小排列后,请返回第 k 个位置上的元素。
重复元素需要分别计数。例如,[5, 5, 2] 的第 2 大元素仍是 5。请使用一个大小不超过 k 的小顶堆完成。
??? tip "解题提示"
1. 第 k 大元素是最大的 k 个数中最小的那个
2. 每个数先入小顶堆,大小超过 k 时弹出最小值
3. 遍历结束时堆中保留最大的 k 个数,堆顶就是答案
LeetCode{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" } 题目解析{ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }
说明: 链接中的题解讲解了快速排序和快速选择,没有使用堆;本练习请按照正文 8.3 节使用大小不超过 k 的小顶堆完成