mirror of
https://github.com/krahets/hello-algo.git
synced 2026-08-29 03:17:13 +00:00
build
This commit is contained in:
@@ -171,7 +171,7 @@ comments: true
|
||||
_maxHeap = nums;
|
||||
// 堆化除叶节点以外的其他所有节点
|
||||
for (int i = _parent(size() - 1); i >= 0; i--) {
|
||||
_siftDown(i);
|
||||
siftDown(i);
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -204,7 +204,7 @@ comments: true
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 完美二叉树的各层节点数量 </p>
|
||||
<p align="center"> 图:完美二叉树的各层节点数量 </p>
|
||||
|
||||
因此,我们可以将各层的“节点数量 $\times$ 节点高度”求和,**从而得到所有节点的堆化迭代次数的总和**。
|
||||
|
||||
|
||||
+40
-6
@@ -11,7 +11,7 @@ comments: true
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 小顶堆与大顶堆 </p>
|
||||
<p align="center"> 图:小顶堆与大顶堆 </p>
|
||||
|
||||
堆作为完全二叉树的一个特例,具有以下特性:
|
||||
|
||||
@@ -333,7 +333,7 @@ comments: true
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 堆的表示与存储 </p>
|
||||
<p align="center"> 图:堆的表示与存储 </p>
|
||||
|
||||
我们可以将索引映射公式封装成函数,方便后续使用。
|
||||
|
||||
@@ -708,6 +708,8 @@ comments: true
|
||||
=== "<9>"
|
||||

|
||||
|
||||
<p align="center"> 图:元素入堆步骤 </p>
|
||||
|
||||
设节点总数为 $n$ ,则树的高度为 $O(\log n)$ 。由此可知,堆化操作的循环轮数最多为 $O(\log n)$ ,**元素入堆操作的时间复杂度为 $O(\log n)$** 。
|
||||
|
||||
=== "Java"
|
||||
@@ -994,10 +996,24 @@ comments: true
|
||||
// 添加节点
|
||||
_maxHeap.add(val);
|
||||
// 从底至顶堆化
|
||||
_siftUp(size() - 1);
|
||||
siftUp(size() - 1);
|
||||
}
|
||||
|
||||
[class]{MaxHeap}-[func]{siftUp}
|
||||
/* 从节点 i 开始,从底至顶堆化 */
|
||||
void siftUp(int i) {
|
||||
while (true) {
|
||||
// 获取节点 i 的父节点
|
||||
int p = _parent(i);
|
||||
// 当“越过根节点”或“节点无需修复”时,结束堆化
|
||||
if (p < 0 || _maxHeap[i] <= _maxHeap[p]) {
|
||||
break;
|
||||
}
|
||||
// 交换两节点
|
||||
_swap(i, p);
|
||||
// 循环向上堆化
|
||||
i = p;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
@@ -1072,6 +1088,8 @@ comments: true
|
||||
=== "<10>"
|
||||

|
||||
|
||||
<p align="center"> 图:堆顶元素出堆步骤 </p>
|
||||
|
||||
与元素入堆操作相似,堆顶元素出堆操作的时间复杂度也为 $O(\log n)$ 。
|
||||
|
||||
=== "Java"
|
||||
@@ -1480,12 +1498,28 @@ comments: true
|
||||
// 删除节点
|
||||
int val = _maxHeap.removeLast();
|
||||
// 从顶至底堆化
|
||||
_siftDown(0);
|
||||
siftDown(0);
|
||||
// 返回堆顶元素
|
||||
return val;
|
||||
}
|
||||
|
||||
[class]{MaxHeap}-[func]{siftDown}
|
||||
/* 从节点 i 开始,从顶至底堆化 */
|
||||
void siftDown(int i) {
|
||||
while (true) {
|
||||
// 判断节点 i, l, r 中值最大的节点,记为 ma
|
||||
int l = _left(i);
|
||||
int r = _right(i);
|
||||
int ma = i;
|
||||
if (l < size() && _maxHeap[l] > _maxHeap[ma]) ma = l;
|
||||
if (r < size() && _maxHeap[r] > _maxHeap[ma]) ma = r;
|
||||
// 若节点 i 最大或索引 l, r 越界,则无需继续堆化,跳出
|
||||
if (ma == i) break;
|
||||
// 交换两节点
|
||||
_swap(i, ma);
|
||||
// 循环向下堆化
|
||||
i = ma;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
+19
-4
@@ -18,11 +18,11 @@ comments: true
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 遍历寻找最大的 k 个元素 </p>
|
||||
<p align="center"> 图:遍历寻找最大的 k 个元素 </p>
|
||||
|
||||
!!! tip
|
||||
|
||||
当 $k = n$ 时,我们可以得到从大到小的序列,等价于「选择排序」算法。
|
||||
当 $k = n$ 时,我们可以得到从大到小的序列,等价于「选择排序」算法。
|
||||
|
||||
## 8.3.2. 方法二:排序
|
||||
|
||||
@@ -32,7 +32,7 @@ comments: true
|
||||
|
||||

|
||||
|
||||
<p align="center"> Fig. 排序寻找最大的 k 个元素 </p>
|
||||
<p align="center"> 图:排序寻找最大的 k 个元素 </p>
|
||||
|
||||
## 8.3.3. 方法三:堆
|
||||
|
||||
@@ -70,6 +70,8 @@ comments: true
|
||||
=== "<9>"
|
||||

|
||||
|
||||
<p align="center"> 图:基于堆寻找最大的 k 个元素 </p>
|
||||
|
||||
总共执行了 $n$ 轮入堆和出堆,堆的最大长度为 $k$ ,因此时间复杂度为 $O(n \log k)$ 。该方法的效率很高,当 $k$ 较小时,时间复杂度趋向 $O(n)$ ;当 $k$ 较大时,时间复杂度不会超过 $O(n \log n)$ 。
|
||||
|
||||
另外,该方法适用于动态数据流的使用场景。在不断加入数据时,我们可以持续维护堆内的元素,从而实现最大 $k$ 个元素的动态更新。
|
||||
@@ -227,7 +229,20 @@ comments: true
|
||||
=== "Dart"
|
||||
|
||||
```dart title="top_k.dart"
|
||||
[class]{}-[func]{top_k_heap}
|
||||
/* 基于堆查找数组中最大的 k 个元素 */
|
||||
MinHeap topKHeap(List<int> nums, int k) {
|
||||
// 将数组的前 k 个元素入堆
|
||||
MinHeap heap = MinHeap(nums.sublist(0, k));
|
||||
// 从第 k+1 个元素开始,保持堆的长度为 k
|
||||
for (int i = k; i < nums.length; i++) {
|
||||
// 若当前元素大于堆顶元素,则将堆顶元素出堆、当前元素入堆
|
||||
if (nums[i] > heap.peek()) {
|
||||
heap.pop();
|
||||
heap.push(nums[i]);
|
||||
}
|
||||
}
|
||||
return heap;
|
||||
}
|
||||
```
|
||||
|
||||
=== "Rust"
|
||||
|
||||
Reference in New Issue
Block a user