Bug fixes and improvements (#1348)

* Add "reference" for EN version. Bug fixes.

* Unify the figure reference as "the figure below" and "the figure above".
Bug fixes.

* Format the EN markdown files.

* Replace "" with <u></u> for EN version and bug fixes

* Fix biary_tree_dfs.png

* Fix biary_tree_dfs.png

* Fix zh-hant/biary_tree_dfs.png

* Fix heap_sort_step1.png

* Sync zh and zh-hant versions.

* Bug fixes

* Fix EN figures

* Bug fixes

* Fix the figure labels for EN version
This commit is contained in:
Yudong Jin
2024-05-06 14:44:48 +08:00
committed by GitHub
parent 8e60d12151
commit c4a7966882
99 changed files with 615 additions and 259 deletions

View File

@ -34,7 +34,7 @@ Starting from the original problem $f(0, n-1)$, perform the binary search throug
2. Recursively solve the subproblem reduced by half in size, which could be $f(i, m-1)$ or $f(m+1, j)$.
3. Repeat steps `1.` and `2.`, until `target` is found or the interval is empty and returns.
The diagram below shows the divide-and-conquer process of binary search for element $6$ in an array.
The figure below shows the divide-and-conquer process of binary search for element $6$ in an array.
![The divide-and-conquer process of binary search](binary_search_recur.assets/binary_search_recur.png)

View File

@ -2,7 +2,7 @@
!!! question
Given the preorder traversal `preorder` and inorder traversal `inorder` of a binary tree, construct the binary tree and return the root node of the binary tree. Assume that there are no duplicate values in the nodes of the binary tree (as shown in the diagram below).
Given the preorder traversal `preorder` and inorder traversal `inorder` of a binary tree, construct the binary tree and return the root node of the binary tree. Assume that there are no duplicate values in the nodes of the binary tree (as shown in the figure below).
![Example data for building a binary tree](build_binary_tree_problem.assets/build_tree_example.png)
@ -20,10 +20,10 @@ Based on the above analysis, this problem can be solved using divide and conquer
By definition, `preorder` and `inorder` can be divided into three parts.
- Preorder traversal: `[ Root | Left Subtree | Right Subtree ]`, for example, the tree in the diagram corresponds to `[ 3 | 9 | 2 1 7 ]`.
- Inorder traversal: `[ Left Subtree | Root | Right Subtree ]`, for example, the tree in the diagram corresponds to `[ 9 | 3 | 1 2 7 ]`.
- Preorder traversal: `[ Root | Left Subtree | Right Subtree ]`, for example, the tree in the figure corresponds to `[ 3 | 9 | 2 1 7 ]`.
- Inorder traversal: `[ Left Subtree | Root | Right Subtree ]`, for example, the tree in the figure corresponds to `[ 9 | 3 | 1 2 7 ]`.
Using the data in the diagram above, we can obtain the division results as shown in the steps below.
Using the data in the figure above, we can obtain the division results as shown in the figure below.
1. The first element 3 in the preorder traversal is the value of the root node.
2. Find the index of the root node 3 in `inorder`, and use this index to divide `inorder` into `[ 9 | 3 1 2 7 ]`.
@ -49,7 +49,7 @@ As shown in the table below, the above variables can represent the index of the
| Left subtree | $i + 1$ | $[l, m-1]$ |
| Right subtree | $i + 1 + (m - l)$ | $[m+1, r]$ |
Please note, the meaning of $(m-l)$ in the right subtree root index is "the number of nodes in the left subtree", which is suggested to be understood in conjunction with the diagram below.
Please note, the meaning of $(m-l)$ in the right subtree root index is "the number of nodes in the left subtree", which is suggested to be understood in conjunction with the figure below.
![Indexes of the root node and left and right subtrees](build_binary_tree_problem.assets/build_tree_division_pointers.png)
@ -61,7 +61,7 @@ To improve the efficiency of querying $m$, we use a hash table `hmap` to store t
[file]{build_tree}-[class]{}-[func]{build_tree}
```
The diagram below shows the recursive process of building the binary tree, where each node is established during the "descending" process, and each edge (reference) is established during the "ascending" process.
The figure below shows the recursive process of building the binary tree, where each node is established during the "descending" process, and each edge (reference) is established during the "ascending" process.
=== "<1>"
![Recursive process of building a binary tree](build_binary_tree_problem.assets/built_tree_step1.png)
@ -90,7 +90,7 @@ The diagram below shows the recursive process of building the binary tree, where
=== "<9>"
![built_tree_step9](build_binary_tree_problem.assets/built_tree_step9.png)
Each recursive function's division results of `preorder` and `inorder` are shown in the diagram below.
Each recursive function's division results of `preorder` and `inorder` are shown in the figure below.
![Division results in each recursive function](build_binary_tree_problem.assets/built_tree_overall.png)

View File

@ -4,7 +4,7 @@ In both merge sorting and building binary trees, we decompose the original probl
!!! question
Given three pillars, denoted as `A`, `B`, and `C`. Initially, pillar `A` is stacked with $n$ discs, arranged in order from top to bottom from smallest to largest. Our task is to move these $n$ discs to pillar `C`, maintaining their original order (as shown below). The following rules must be followed during the disc movement process:
Given three pillars, denoted as `A`, `B`, and `C`. Initially, pillar `A` is stacked with $n$ discs, arranged in order from top to bottom from smallest to largest. Our task is to move these $n$ discs to pillar `C`, maintaining their original order (as shown in the figure below). The following rules must be followed during the disc movement process:
1. A disc can only be picked up from the top of a pillar and placed on top of another pillar.
2. Only one disc can be moved at a time.
@ -16,7 +16,7 @@ In both merge sorting and building binary trees, we decompose the original probl
### Consider the base case
As shown below, for the problem $f(1)$, i.e., when there is only one disc, we can directly move it from `A` to `C`.
As shown in the figure below, for the problem $f(1)$, i.e., when there is only one disc, we can directly move it from `A` to `C`.
=== "<1>"
![Solution for a problem of size 1](hanota_problem.assets/hanota_f1_step1.png)
@ -24,7 +24,7 @@ As shown below, for the problem $f(1)$, i.e., when there is only one disc, we ca
=== "<2>"
![hanota_f1_step2](hanota_problem.assets/hanota_f1_step2.png)
As shown below, for the problem $f(2)$, i.e., when there are two discs, **since the smaller disc must always be above the larger disc, `B` is needed to assist in the movement**.
As shown in the figure below, for the problem $f(2)$, i.e., when there are two discs, **since the smaller disc must always be above the larger disc, `B` is needed to assist in the movement**.
1. First, move the smaller disc from `A` to `B`.
2. Then move the larger disc from `A` to `C`.
@ -48,7 +48,7 @@ The process of solving the problem $f(2)$ can be summarized as: **moving two dis
For the problem $f(3)$, i.e., when there are three discs, the situation becomes slightly more complicated.
Since we already know the solutions to $f(1)$ and $f(2)$, we can think from a divide-and-conquer perspective and **consider the two top discs on `A` as a unit**, performing the steps shown below. This way, the three discs are successfully moved from `A` to `C`.
Since we already know the solutions to $f(1)$ and $f(2)$, we can think from a divide-and-conquer perspective and **consider the two top discs on `A` as a unit**, performing the steps shown in the figure below. This way, the three discs are successfully moved from `A` to `C`.
1. Let `B` be the target pillar and `C` the buffer pillar, and move the two discs from `A` to `B`.
2. Move the remaining disc from `A` directly to `C`.
@ -68,7 +68,7 @@ Since we already know the solutions to $f(1)$ and $f(2)$, we can think from a di
Essentially, **we divide the problem $f(3)$ into two subproblems $f(2)$ and one subproblem $f(1)$**. By solving these three subproblems in order, the original problem is resolved. This indicates that the subproblems are independent, and their solutions can be merged.
From this, we can summarize the divide-and-conquer strategy for solving the Tower of Hanoi shown in the following image: divide the original problem $f(n)$ into two subproblems $f(n-1)$ and one subproblem $f(1)$, and solve these three subproblems in the following order.
From this, we can summarize the divide-and-conquer strategy for solving the Tower of Hanoi shown in the figure below: divide the original problem $f(n)$ into two subproblems $f(n-1)$ and one subproblem $f(1)$, and solve these three subproblems in the following order.
1. Move $n-1$ discs with the help of `C` from `A` to `B`.
2. Move the remaining one disc directly from `A` to `C`.
@ -86,7 +86,7 @@ In the code, we declare a recursive function `dfs(i, src, buf, tar)` whose role
[file]{hanota}-[class]{}-[func]{solve_hanota}
```
As shown below, the Tower of Hanoi forms a recursive tree with a height of $n$, each node representing a subproblem, corresponding to an open `dfs()` function, **thus the time complexity is $O(2^n)$, and the space complexity is $O(n)$**.
As shown in the figure below, the Tower of Hanoi forms a recursive tree with a height of $n$, each node representing a subproblem, corresponding to an open `dfs()` function, **thus the time complexity is $O(2^n)$, and the space complexity is $O(n)$**.
![Recursive tree of the Tower of Hanoi](hanota_problem.assets/hanota_recursive_tree.png)