mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-23 11:46:08 +00:00
93 lines
4.0 KiB
Markdown
93 lines
4.0 KiB
Markdown
---
|
||
comments: true
|
||
---
|
||
|
||
# 8.5 練習
|
||
|
||
## 8.5.1 知識鞏固
|
||
|
||
### 1. 數字 10 入堆積後怎樣調整
|
||
|
||
陣列 `[9, 7, 8, 3, 5]` 表示一個大頂堆積。現在將數字 10 入堆積。
|
||
|
||
<!-- numbered-subquestions -->
|
||
|
||
1. 先把 10 新增到陣列末尾,它的父節點值是多少?
|
||
2. 從新節點開始向上堆積化,寫出每次交換後的陣列。
|
||
3. 最終的堆積頂元素是什麼?一共交換了幾次?
|
||
|
||
??? 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 次。
|
||
|
||
### 2. 檢查小頂堆積的父子關係
|
||
|
||
陣列 `[1, 4, 3, 7, 6, 2]` 表示一棵完全二元樹。小頂堆積要求每個父節點都不大於它的孩子。
|
||
對索引 $i$,左、右孩子索引分別為 $2i+1$ 和 $2i+2$。
|
||
|
||
<!-- numbered-subquestions -->
|
||
|
||
1. 索引 2 的孩子索引和值分別是什麼?
|
||
2. 索引 2 處的節點值為 3,它與孩子節點之間是否違反小頂堆積規則?如果違反,應交換哪兩個元素?
|
||
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`。
|
||
所有父節點都不大於自己的孩子,因此現在滿足小頂堆積規則。
|
||
|
||
### 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 個數。
|
||
|
||
## 8.5.2 程式設計練習
|
||
|
||
### 1. 尋找陣列中的第 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](https://leetcode.cn/problems/kth-largest-element-in-an-array/){ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" } [題目解析](https://leetcode.cn/problems/kth-largest-element-in-an-array/solutions/2361969/215-shu-zu-zhong-de-di-k-ge-zui-da-yuan-d786p/){ .rounded-button .exercise-button target="_blank" rel="noopener noreferrer" }
|
||
|
||
> **說明:** 連結中的題解講解了快速排序和快速選擇,沒有使用堆積;本練習請按照正文 8.3 節使用大小不超過 k 的小頂堆積完成
|