mirror of
https://github.com/krahets/hello-algo.git
synced 2024-12-25 00:46:30 +08:00
Update the symbols of the animations.
This commit is contained in:
parent
0b72fef381
commit
3daaf30f23
10 changed files with 89 additions and 89 deletions
|
@ -32,7 +32,7 @@ comments: true
|
|||
| 浮点数 | **float** | 4 bytes | $-3.4 \times 10^{38}$ ~ $3.4 \times 10^{38}$ | $0.0$ f |
|
||||
| | double | 8 bytes | $-1.7 \times 10^{308}$ ~ $1.7 \times 10^{308}$ | $0.0$ |
|
||||
| 字符 | **char** | 2 bytes / 1 byte | $0$ ~ $2^{16} - 1$ | $0$ |
|
||||
| 布尔 | **boolean(bool)** | 1 byte / 1 bit | $\text{true}$ 或 $\text{false}$ | $\text{false}$ |
|
||||
| 布尔 | **bool** | 1 byte / 1 bit | $\text{true}$ 或 $\text{false}$ | $\text{false}$ |
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
@ -90,37 +90,37 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
|
|||
|
||||
代码相对抽象,建议对照以下动画图示来加深理解。
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![graph_bfs_step1](graph_traversal.assets/graph_bfs_step1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![graph_bfs_step2](graph_traversal.assets/graph_bfs_step2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![graph_bfs_step3](graph_traversal.assets/graph_bfs_step3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![graph_bfs_step4](graph_traversal.assets/graph_bfs_step4.png)
|
||||
|
||||
=== "Step 5"
|
||||
=== "<5>"
|
||||
![graph_bfs_step5](graph_traversal.assets/graph_bfs_step5.png)
|
||||
|
||||
=== "Step 6"
|
||||
=== "<6>"
|
||||
![graph_bfs_step6](graph_traversal.assets/graph_bfs_step6.png)
|
||||
|
||||
=== "Step 7"
|
||||
=== "<7>"
|
||||
![graph_bfs_step7](graph_traversal.assets/graph_bfs_step7.png)
|
||||
|
||||
=== "Step 8"
|
||||
=== "<8>"
|
||||
![graph_bfs_step8](graph_traversal.assets/graph_bfs_step8.png)
|
||||
|
||||
=== "Step 9"
|
||||
=== "<9>"
|
||||
![graph_bfs_step9](graph_traversal.assets/graph_bfs_step9.png)
|
||||
|
||||
=== "Step 10"
|
||||
=== "<10>"
|
||||
![graph_bfs_step10](graph_traversal.assets/graph_bfs_step10.png)
|
||||
|
||||
=== "Step 11"
|
||||
=== "<11>"
|
||||
![graph_bfs_step11](graph_traversal.assets/graph_bfs_step11.png)
|
||||
|
||||
!!! question "广度优先遍历的序列是否唯一?"
|
||||
|
@ -212,37 +212,37 @@ BFS 常借助「队列」来实现。队列具有“先入先出”的性质,
|
|||
|
||||
为了加深理解,请你将图示与代码结合起来,在脑中(或者用笔画下来)模拟整个 DFS 过程,包括每个递归方法何时开启、何时返回。
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![graph_dfs_step1](graph_traversal.assets/graph_dfs_step1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![graph_dfs_step2](graph_traversal.assets/graph_dfs_step2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![graph_dfs_step3](graph_traversal.assets/graph_dfs_step3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![graph_dfs_step4](graph_traversal.assets/graph_dfs_step4.png)
|
||||
|
||||
=== "Step 5"
|
||||
=== "<5>"
|
||||
![graph_dfs_step5](graph_traversal.assets/graph_dfs_step5.png)
|
||||
|
||||
=== "Step 6"
|
||||
=== "<6>"
|
||||
![graph_dfs_step6](graph_traversal.assets/graph_dfs_step6.png)
|
||||
|
||||
=== "Step 7"
|
||||
=== "<7>"
|
||||
![graph_dfs_step7](graph_traversal.assets/graph_dfs_step7.png)
|
||||
|
||||
=== "Step 8"
|
||||
=== "<8>"
|
||||
![graph_dfs_step8](graph_traversal.assets/graph_dfs_step8.png)
|
||||
|
||||
=== "Step 9"
|
||||
=== "<9>"
|
||||
![graph_dfs_step9](graph_traversal.assets/graph_dfs_step9.png)
|
||||
|
||||
=== "Step 10"
|
||||
=== "<10>"
|
||||
![graph_dfs_step10](graph_traversal.assets/graph_dfs_step10.png)
|
||||
|
||||
=== "Step 11"
|
||||
=== "<11>"
|
||||
![graph_dfs_step11](graph_traversal.assets/graph_dfs_step11.png)
|
||||
|
||||
!!! question "深度优先遍历的序列是否唯一?"
|
||||
|
|
|
@ -454,22 +454,22 @@ comments: true
|
|||
|
||||
考虑从入堆结点开始,**从底至顶执行堆化**。具体地,比较插入结点与其父结点的值,若插入结点更大则将它们交换;并循环以上操作,从底至顶地修复堆中的各个结点;直至越过根结点时结束,或当遇到无需交换的结点时提前结束。
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![heap_push_step1](heap.assets/heap_push_step1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![heap_push_step2](heap.assets/heap_push_step2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![heap_push_step3](heap.assets/heap_push_step3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![heap_push_step4](heap.assets/heap_push_step4.png)
|
||||
|
||||
=== "Step 5"
|
||||
=== "<5>"
|
||||
![heap_push_step5](heap.assets/heap_push_step5.png)
|
||||
|
||||
=== "Step 6"
|
||||
=== "<6>"
|
||||
![heap_push_step6](heap.assets/heap_push_step6.png)
|
||||
|
||||
设结点总数为 $n$ ,则树的高度为 $O(\log n)$ ,易得堆化操作的循环轮数最多为 $O(\log n)$ ,**因而元素入堆操作的时间复杂度为 $O(\log n)$** 。
|
||||
|
@ -562,34 +562,34 @@ comments: true
|
|||
|
||||
顾名思义,**从顶至底堆化的操作方向与从底至顶堆化相反**,我们比较根结点的值与其两个子结点的值,将最大的子结点与根结点执行交换,并循环以上操作,直到越过叶结点时结束,或当遇到无需交换的结点时提前结束。
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![heap_poll_step1](heap.assets/heap_poll_step1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![heap_poll_step2](heap.assets/heap_poll_step2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![heap_poll_step3](heap.assets/heap_poll_step3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![heap_poll_step4](heap.assets/heap_poll_step4.png)
|
||||
|
||||
=== "Step 5"
|
||||
=== "<5>"
|
||||
![heap_poll_step5](heap.assets/heap_poll_step5.png)
|
||||
|
||||
=== "Step 6"
|
||||
=== "<6>"
|
||||
![heap_poll_step6](heap.assets/heap_poll_step6.png)
|
||||
|
||||
=== "Step 7"
|
||||
=== "<7>"
|
||||
![heap_poll_step7](heap.assets/heap_poll_step7.png)
|
||||
|
||||
=== "Step 8"
|
||||
=== "<8>"
|
||||
![heap_poll_step8](heap.assets/heap_poll_step8.png)
|
||||
|
||||
=== "Step 9"
|
||||
=== "<9>"
|
||||
![heap_poll_step9](heap.assets/heap_poll_step9.png)
|
||||
|
||||
=== "Step 10"
|
||||
=== "<10>"
|
||||
![heap_poll_step10](heap.assets/heap_poll_step10.png)
|
||||
|
||||
与元素入堆操作类似,**堆顶元素出堆操作的时间复杂度为 $O(\log n)$** 。
|
||||
|
|
|
@ -18,15 +18,15 @@ comments: true
|
|||
2. 由于在英文字母表中 $r$ 在 $m$ 的后面,因此应排除字典前半部分,查找范围仅剩后半部分;
|
||||
3. 循环执行步骤 1-2 ,直到找到拼音首字母为 $r$ 的页码时终止。
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![look_up_dictionary_step_1](algorithms_are_everywhere.assets/look_up_dictionary_step_1.png)
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![look_up_dictionary_step_2](algorithms_are_everywhere.assets/look_up_dictionary_step_2.png)
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![look_up_dictionary_step_3](algorithms_are_everywhere.assets/look_up_dictionary_step_3.png)
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![look_up_dictionary_step_4](algorithms_are_everywhere.assets/look_up_dictionary_step_4.png)
|
||||
=== "Step 5"
|
||||
=== "<5>"
|
||||
![look_up_dictionary_step_5](algorithms_are_everywhere.assets/look_up_dictionary_step_5.png)
|
||||
|
||||
查字典这个小学生的标配技能,实际上就是大名鼎鼎的「二分查找」。从数据结构角度,我们可以将字典看作是一个已排序的「数组」;而从算法角度,我们可将上述查字典的一系列指令看作是「二分查找」算法。
|
||||
|
|
|
@ -28,25 +28,25 @@ $$
|
|||
|
||||
首先,我们先采用“双闭区间”的表示,在数组 `nums` 中查找目标元素 `target` 的对应索引。
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![binary_search_step1](binary_search.assets/binary_search_step1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![binary_search_step2](binary_search.assets/binary_search_step2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![binary_search_step3](binary_search.assets/binary_search_step3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![binary_search_step4](binary_search.assets/binary_search_step4.png)
|
||||
|
||||
=== "Step 5"
|
||||
=== "<5>"
|
||||
![binary_search_step5](binary_search.assets/binary_search_step5.png)
|
||||
|
||||
=== "Step 6"
|
||||
=== "<6>"
|
||||
![binary_search_step6](binary_search.assets/binary_search_step6.png)
|
||||
|
||||
=== "Step 7"
|
||||
=== "<7>"
|
||||
![binary_search_step7](binary_search.assets/binary_search_step7.png)
|
||||
|
||||
二分查找“双闭区间”表示下的代码如下所示。
|
||||
|
|
|
@ -14,25 +14,25 @@ comments: true
|
|||
|
||||
完成此次冒泡操作后,**数组最大元素已在正确位置,接下来只需排序剩余 $n - 1$ 个元素**。
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![bubble_operation_step1](bubble_sort.assets/bubble_operation_step1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![bubble_operation_step2](bubble_sort.assets/bubble_operation_step2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![bubble_operation_step3](bubble_sort.assets/bubble_operation_step3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![bubble_operation_step4](bubble_sort.assets/bubble_operation_step4.png)
|
||||
|
||||
=== "Step 5"
|
||||
=== "<5>"
|
||||
![bubble_operation_step5](bubble_sort.assets/bubble_operation_step5.png)
|
||||
|
||||
=== "Step 6"
|
||||
=== "<6>"
|
||||
![bubble_operation_step6](bubble_sort.assets/bubble_operation_step6.png)
|
||||
|
||||
=== "Step 7"
|
||||
=== "<7>"
|
||||
![bubble_operation_step7](bubble_sort.assets/bubble_operation_step7.png)
|
||||
|
||||
<p align="center"> Fig. 冒泡操作 </p>
|
||||
|
|
|
@ -24,34 +24,34 @@ comments: true
|
|||
|
||||
需要注意,由于从长度为 1 的子数组开始合并,所以 **每个子数组都是有序的**。因此,合并任务本质是要 **将两个有序子数组合并为一个有序数组**。
|
||||
|
||||
=== "Step1"
|
||||
=== "<1>"
|
||||
![merge_sort_step1](merge_sort.assets/merge_sort_step1.png)
|
||||
|
||||
=== "Step2"
|
||||
=== "<2>"
|
||||
![merge_sort_step2](merge_sort.assets/merge_sort_step2.png)
|
||||
|
||||
=== "Step3"
|
||||
=== "<3>"
|
||||
![merge_sort_step3](merge_sort.assets/merge_sort_step3.png)
|
||||
|
||||
=== "Step4"
|
||||
=== "<4>"
|
||||
![merge_sort_step4](merge_sort.assets/merge_sort_step4.png)
|
||||
|
||||
=== "Step5"
|
||||
=== "<5>"
|
||||
![merge_sort_step5](merge_sort.assets/merge_sort_step5.png)
|
||||
|
||||
=== "Step6"
|
||||
=== "<6>"
|
||||
![merge_sort_step6](merge_sort.assets/merge_sort_step6.png)
|
||||
|
||||
=== "Step7"
|
||||
=== "<7>"
|
||||
![merge_sort_step7](merge_sort.assets/merge_sort_step7.png)
|
||||
|
||||
=== "Step8"
|
||||
=== "<8>"
|
||||
![merge_sort_step8](merge_sort.assets/merge_sort_step8.png)
|
||||
|
||||
=== "Step9"
|
||||
=== "<9>"
|
||||
![merge_sort_step9](merge_sort.assets/merge_sort_step9.png)
|
||||
|
||||
=== "Step10"
|
||||
=== "<10>"
|
||||
![merge_sort_step10](merge_sort.assets/merge_sort_step10.png)
|
||||
|
||||
观察发现,归并排序的递归顺序就是二叉树的「后序遍历」。
|
||||
|
|
|
@ -14,31 +14,31 @@ comments: true
|
|||
|
||||
「哨兵划分」执行完毕后,原数组被划分成两个部分,即 **左子数组** 和 **右子数组**,且满足 **左子数组任意元素 < 基准数 < 右子数组任意元素**。因此,接下来我们只需要排序两个子数组即可。
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![pivot_division_step1](quick_sort.assets/pivot_division_step1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![pivot_division_step2](quick_sort.assets/pivot_division_step2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![pivot_division_step3](quick_sort.assets/pivot_division_step3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![pivot_division_step4](quick_sort.assets/pivot_division_step4.png)
|
||||
|
||||
=== "Step 5"
|
||||
=== "<5>"
|
||||
![pivot_division_step5](quick_sort.assets/pivot_division_step5.png)
|
||||
|
||||
=== "Step 6"
|
||||
=== "<6>"
|
||||
![pivot_division_step6](quick_sort.assets/pivot_division_step6.png)
|
||||
|
||||
=== "Step 7"
|
||||
=== "<7>"
|
||||
![pivot_division_step7](quick_sort.assets/pivot_division_step7.png)
|
||||
|
||||
=== "Step 8"
|
||||
=== "<8>"
|
||||
![pivot_division_step8](quick_sort.assets/pivot_division_step8.png)
|
||||
|
||||
=== "Step 9"
|
||||
=== "<9>"
|
||||
![pivot_division_step9](quick_sort.assets/pivot_division_step9.png)
|
||||
|
||||
<p align="center"> Fig. 哨兵划分 </p>
|
||||
|
|
|
@ -313,16 +313,16 @@ AVL 树的独特之处在于「旋转 Rotation」的操作,其可 **在不影
|
|||
|
||||
如下图所示(结点下方为「平衡因子」),从底至顶看,二叉树中首个失衡结点是 **结点 3**。我们聚焦在以该失衡结点为根结点的子树上,将该结点记为 `node` ,将其左子结点记为 `child` ,执行「右旋」操作。完成右旋后,该子树已经恢复平衡,并且仍然为二叉搜索树。
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![right_rotate_step1](avl_tree.assets/right_rotate_step1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![right_rotate_step2](avl_tree.assets/right_rotate_step2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![right_rotate_step3](avl_tree.assets/right_rotate_step3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![right_rotate_step4](avl_tree.assets/right_rotate_step4.png)
|
||||
|
||||
进而,如果结点 `child` 本身有右子结点(记为 `grandChild` ),则需要在「右旋」中添加一步:将 `grandChild` 作为 `node` 的左子结点。
|
||||
|
|
|
@ -21,16 +21,16 @@ comments: true
|
|||
- 若 `cur.val > num` ,说明目标结点在 `cur` 的左子树中,因此执行 `cur = cur.left` ;
|
||||
- 若 `cur.val = num` ,说明找到目标结点,跳出循环并返回该结点即可;
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![bst_search_1](binary_search_tree.assets/bst_search_1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![bst_search_2](binary_search_tree.assets/bst_search_2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![bst_search_3](binary_search_tree.assets/bst_search_3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![bst_search_4](binary_search_tree.assets/bst_search_4.png)
|
||||
|
||||
二叉搜索树的查找操作和二分查找算法如出一辙,也是在每轮排除一半情况。循环次数最多为二叉树的高度,当二叉树平衡时,使用 $O(\log n)$ 时间。
|
||||
|
@ -188,16 +188,16 @@ comments: true
|
|||
2. 在树中递归删除结点 `nex` ;
|
||||
3. 使用 `nex` 替换待删除结点;
|
||||
|
||||
=== "Step 1"
|
||||
=== "<1>"
|
||||
![bst_remove_case3_1](binary_search_tree.assets/bst_remove_case3_1.png)
|
||||
|
||||
=== "Step 2"
|
||||
=== "<2>"
|
||||
![bst_remove_case3_2](binary_search_tree.assets/bst_remove_case3_2.png)
|
||||
|
||||
=== "Step 3"
|
||||
=== "<3>"
|
||||
![bst_remove_case3_3](binary_search_tree.assets/bst_remove_case3_3.png)
|
||||
|
||||
=== "Step 4"
|
||||
=== "<4>"
|
||||
![bst_remove_case3_4](binary_search_tree.assets/bst_remove_case3_4.png)
|
||||
|
||||
删除结点操作也使用 $O(\log n)$ 时间,其中查找待删除结点 $O(\log n)$ ,获取中序遍历后继结点 $O(\log n)$ 。
|
||||
|
|
Loading…
Reference in a new issue