Skip to content

Commit

Permalink
Bug fixes and improvements (#1348)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
krahets committed May 6, 2024
1 parent 8e60d12 commit c4a7966
Show file tree
Hide file tree
Showing 99 changed files with 615 additions and 259 deletions.
2 changes: 1 addition & 1 deletion codes/c/chapter_hashing/simple_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ int rotHash(char *key) {

/* Driver Code */
int main() {
char *key = "Hello dsad3241241dsa算123法";
char *key = "Hello 算法";

int hash = addHash(key);
printf("加法哈希值为 %d\n", hash);
Expand Down
2 changes: 1 addition & 1 deletion codes/cpp/chapter_hashing/simple_hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ int rotHash(string key) {

/* Driver Code */
int main() {
string key = "Hello dsad3241241dsa算123法";
string key = "Hello 算法";

int hash = addHash(key);
cout << "加法哈希值为 " << hash << endl;
Expand Down
4 changes: 2 additions & 2 deletions codes/javascript/chapter_dynamic_programming/coin_change.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function coinChangeDP(coins, amt) {
return dp[n][amt] !== MAX ? dp[n][amt] : -1;
}

/* 零钱兑换:状态压缩后的动态规划 */
/* 零钱兑换:空间优化后的动态规划 */
function coinChangeDPComp(coins, amt) {
const n = coins.length;
const MAX = amt + 1;
Expand Down Expand Up @@ -61,6 +61,6 @@ const amt = 4;
let res = coinChangeDP(coins, amt);
console.log(`凑到目标金额所需的最少硬币数量为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = coinChangeDPComp(coins, amt);
console.log(`凑到目标金额所需的最少硬币数量为 ${res}`);
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function coinChangeIIDP(coins, amt) {
return dp[n][amt];
}

/* 零钱兑换 II:状态压缩后的动态规划 */
/* 零钱兑换 II:空间优化后的动态规划 */
function coinChangeIIDPComp(coins, amt) {
const n = coins.length;
// 初始化 dp 表
Expand Down Expand Up @@ -59,6 +59,6 @@ const amt = 5;
let res = coinChangeIIDP(coins, amt);
console.log(`凑出目标金额的硬币组合数量为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = coinChangeIIDPComp(coins, amt);
console.log(`凑出目标金额的硬币组合数量为 ${res}`);
4 changes: 2 additions & 2 deletions codes/javascript/chapter_dynamic_programming/edit_distance.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ function editDistanceDP(s, t) {
return dp[n][m];
}

/* 编辑距离:状态压缩后的动态规划 */
/* 编辑距离:空间优化后的动态规划 */
function editDistanceDPComp(s, t) {
const n = s.length,
m = t.length;
Expand Down Expand Up @@ -130,6 +130,6 @@ console.log(`将 ${s} 更改为 ${t} 最少需要编辑 ${res} 步`);
res = editDistanceDP(s, t);
console.log(`将 ${s} 更改为 ${t} 最少需要编辑 ${res} 步`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = editDistanceDPComp(s, t);
console.log(`将 ${s} 更改为 ${t} 最少需要编辑 ${res} 步`);
4 changes: 2 additions & 2 deletions codes/javascript/chapter_dynamic_programming/knapsack.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function knapsackDP(wgt, val, cap) {
return dp[n][cap];
}

/* 0-1 背包:状态压缩后的动态规划 */
/* 0-1 背包:空间优化后的动态规划 */
function knapsackDPComp(wgt, val, cap) {
const n = wgt.length;
// 初始化 dp 表
Expand Down Expand Up @@ -108,6 +108,6 @@ console.log(`不超过背包容量的最大物品价值为 ${res}`);
res = knapsackDP(wgt, val, cap);
console.log(`不超过背包容量的最大物品价值为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = knapsackDPComp(wgt, val, cap);
console.log(`不超过背包容量的最大物品价值为 ${res}`);
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function minCostClimbingStairsDP(cost) {
return dp[n];
}

/* 爬楼梯最小代价:状态压缩后的动态规划 */
/* 爬楼梯最小代价:空间优化后的动态规划 */
function minCostClimbingStairsDPComp(cost) {
const n = cost.length - 1;
if (n === 1 || n === 2) {
Expand Down
4 changes: 2 additions & 2 deletions codes/javascript/chapter_dynamic_programming/min_path_sum.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ function minPathSumDP(grid) {
return dp[n - 1][m - 1];
}

/* 最小路径和:状态压缩后的动态规划 */
/* 最小路径和:空间优化后的动态规划 */
function minPathSumDPComp(grid) {
const n = grid.length,
m = grid[0].length;
Expand Down Expand Up @@ -116,6 +116,6 @@ console.log(`从左上角到右下角的最小路径和为 ${res}`);
res = minPathSumDP(grid);
console.log(`从左上角到右下角的最小路径和为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = minPathSumDPComp(grid);
console.log(`从左上角到右下角的最小路径和为 ${res}`);
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function unboundedKnapsackDP(wgt, val, cap) {
return dp[n][cap];
}

/* 完全背包:状态压缩后的动态规划 */
/* 完全背包:空间优化后的动态规划 */
function unboundedKnapsackDPComp(wgt, val, cap) {
const n = wgt.length;
// 初始化 dp 表
Expand Down Expand Up @@ -58,6 +58,6 @@ const cap = 4;
let res = unboundedKnapsackDP(wgt, val, cap);
console.log(`不超过背包容量的最大物品价值为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = unboundedKnapsackDPComp(wgt, val, cap);
console.log(`不超过背包容量的最大物品价值为 ${res}`);
3 changes: 1 addition & 2 deletions codes/ruby/chapter_sorting/quick_sort.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class QuickSort
class << self
### 哨兵划分 ###
def partition(nums, left, right)

# 以 nums[left] 为基准数
i, j = left, right
while i < j
Expand Down Expand Up @@ -116,7 +115,7 @@ def partition(nums, left, right)
i # 返回基准数的索引
end

### 快速排序(尾递归优化)
### 快速排序(尾递归优化)###
def quick_sort(nums, left, right)
# 子数组长度不为 1 时递归
while left < right
Expand Down
4 changes: 2 additions & 2 deletions codes/typescript/chapter_dynamic_programming/coin_change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function coinChangeDP(coins: Array<number>, amt: number): number {
return dp[n][amt] !== MAX ? dp[n][amt] : -1;
}

/* 零钱兑换:状态压缩后的动态规划 */
/* 零钱兑换:空间优化后的动态规划 */
function coinChangeDPComp(coins: Array<number>, amt: number): number {
const n = coins.length;
const MAX = amt + 1;
Expand Down Expand Up @@ -61,7 +61,7 @@ const amt = 4;
let res = coinChangeDP(coins, amt);
console.log(`凑到目标金额所需的最少硬币数量为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = coinChangeDPComp(coins, amt);
console.log(`凑到目标金额所需的最少硬币数量为 ${res}`);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ function coinChangeIIDP(coins: Array<number>, amt: number): number {
return dp[n][amt];
}

/* 零钱兑换 II:状态压缩后的动态规划 */
/* 零钱兑换 II:空间优化后的动态规划 */
function coinChangeIIDPComp(coins: Array<number>, amt: number): number {
const n = coins.length;
// 初始化 dp 表
Expand Down Expand Up @@ -59,7 +59,7 @@ const amt = 5;
let res = coinChangeIIDP(coins, amt);
console.log(`凑出目标金额的硬币组合数量为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = coinChangeIIDPComp(coins, amt);
console.log(`凑出目标金额的硬币组合数量为 ${res}`);

Expand Down
4 changes: 2 additions & 2 deletions codes/typescript/chapter_dynamic_programming/edit_distance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ function editDistanceDP(s: string, t: string): number {
return dp[n][m];
}

/* 编辑距离:状态压缩后的动态规划 */
/* 编辑距离:空间优化后的动态规划 */
function editDistanceDPComp(s: string, t: string): number {
const n = s.length,
m = t.length;
Expand Down Expand Up @@ -141,7 +141,7 @@ console.log(`将 ${s} 更改为 ${t} 最少需要编辑 ${res} 步`);
res = editDistanceDP(s, t);
console.log(`将 ${s} 更改为 ${t} 最少需要编辑 ${res} 步`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = editDistanceDPComp(s, t);
console.log(`将 ${s} 更改为 ${t} 最少需要编辑 ${res} 步`);

Expand Down
4 changes: 2 additions & 2 deletions codes/typescript/chapter_dynamic_programming/knapsack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ function knapsackDP(
return dp[n][cap];
}

/* 0-1 背包:状态压缩后的动态规划 */
/* 0-1 背包:空间优化后的动态规划 */
function knapsackDPComp(
wgt: Array<number>,
val: Array<number>,
Expand Down Expand Up @@ -127,7 +127,7 @@ console.log(`不超过背包容量的最大物品价值为 ${res}`);
res = knapsackDP(wgt, val, cap);
console.log(`不超过背包容量的最大物品价值为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = knapsackDPComp(wgt, val, cap);
console.log(`不超过背包容量的最大物品价值为 ${res}`);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ function minCostClimbingStairsDP(cost: Array<number>): number {
return dp[n];
}

/* 爬楼梯最小代价:状态压缩后的动态规划 */
/* 爬楼梯最小代价:空间优化后的动态规划 */
function minCostClimbingStairsDPComp(cost: Array<number>): number {
const n = cost.length - 1;
if (n === 1 || n === 2) {
Expand Down
4 changes: 2 additions & 2 deletions codes/typescript/chapter_dynamic_programming/min_path_sum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ function minPathSumDP(grid: Array<Array<number>>): number {
return dp[n - 1][m - 1];
}

/* 最小路径和:状态压缩后的动态规划 */
/* 最小路径和:空间优化后的动态规划 */
function minPathSumDPComp(grid: Array<Array<number>>): number {
const n = grid.length,
m = grid[0].length;
Expand Down Expand Up @@ -125,7 +125,7 @@ console.log(`从左上角到右下角的最小路径和为 ${res}`);
res = minPathSumDP(grid);
console.log(`从左上角到右下角的最小路径和为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = minPathSumDPComp(grid);
console.log(`从左上角到右下角的最小路径和为 ${res}`);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function unboundedKnapsackDP(
return dp[n][cap];
}

/* 完全背包:状态压缩后的动态规划 */
/* 完全背包:空间优化后的动态规划 */
function unboundedKnapsackDPComp(
wgt: Array<number>,
val: Array<number>,
Expand Down Expand Up @@ -66,7 +66,7 @@ const cap = 4;
let res = unboundedKnapsackDP(wgt, val, cap);
console.log(`不超过背包容量的最大物品价值为 ${res}`);

// 状态压缩后的动态规划
// 空间优化后的动态规划
res = unboundedKnapsackDPComp(wgt, val, cap);
console.log(`不超过背包容量的最大物品价值为 ${res}`);

Expand Down
2 changes: 1 addition & 1 deletion docs/chapter_backtracking/n_queens_problem.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

也就是说,我们可以采取逐行放置策略:从第一行开始,在每行放置一个皇后,直至最后一行结束。

下图所示为 $4$ 皇后问题的逐行放置过程。受画幅限制,下图仅展开了第一行的其中一个搜索分支,并且将不满足列约束和对角线约束的方案都进行了剪枝。
下图所示为 4 皇后问题的逐行放置过程。受画幅限制,下图仅展开了第一行的其中一个搜索分支,并且将不满足列约束和对角线约束的方案都进行了剪枝。

![逐行放置策略](n_queens_problem.assets/n_queens_placing.png)

Expand Down
Binary file modified docs/chapter_sorting/heap_sort.assets/heap_sort_step1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified docs/chapter_tree/binary_tree_traversal.assets/binary_tree_dfs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified en/docs/chapter_appendix/contribution.assets/edit_markdown.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion en/docs/chapter_appendix/contribution.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ As shown in the figure below, there is an "edit icon" in the upper right corner

![Edit page button](contribution.assets/edit_markdown.png)

Images cannot be directly modified and require the creation of a new [Issue](https://github.com/krahets/hello-algo/issues) or a comment to describe the problem. We will redraw and replace the images as soon as possible.
Figures cannot be directly modified and require the creation of a new [Issue](https://github.com/krahets/hello-algo/issues) or a comment to describe the problem. We will redraw and replace the figures as soon as possible.

### Content creation

Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion en/docs/chapter_appendix/installation.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ We recommend using the open-source, lightweight VS Code as your local Integrated

![Download VS Code from the official website](installation.assets/vscode_installation.png)

VS Code has a powerful extension ecosystem, supporting the execution and debugging of most programming languages. For example, after installing the "Python Extension Pack," you can debug Python code. The installation steps are shown in the following figure.
VS Code has a powerful extension ecosystem, supporting the execution and debugging of most programming languages. For example, after installing the "Python Extension Pack," you can debug Python code. The installation steps are shown in the figure below.

![Install VS Code Extension Pack](installation.assets/vscode_extension_installation.png)

Expand Down
6 changes: 3 additions & 3 deletions en/docs/chapter_array_and_linkedlist/array.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Array

An "array" is a linear data structure that operates as a lineup of similar items, stored together in a computer's memory in contiguous spaces. It's like a sequence that maintains organized storage. Each item in this lineup has its unique 'spot' known as an "index". Please refer to the figure below to observe how arrays work and grasp these key terms.
An <u>array</u> is a linear data structure that operates as a lineup of similar items, stored together in a computer's memory in contiguous spaces. It's like a sequence that maintains organized storage. Each item in this lineup has its unique 'spot' known as an <u>index</u>. Please refer to the figure below to observe how arrays work and grasp these key terms.

![Array definition and storage method](array.assets/array_definition.png)

Expand Down Expand Up @@ -125,7 +125,7 @@ Elements in an array are stored in contiguous memory spaces, making it simpler t

![Memory address calculation for array elements](array.assets/array_memory_location_calculation.png)

As observed in the above illustration, array indexing conventionally begins at $0$. While this might appear counterintuitive, considering counting usually starts at $1$, within the address calculation formula, **an index is essentially an offset from the memory address**. For the first element's address, this offset is $0$, validating its index as $0$.
As observed in the figure above, array indexing conventionally begins at $0$. While this might appear counterintuitive, considering counting usually starts at $1$, within the address calculation formula, **an index is essentially an offset from the memory address**. For the first element's address, this offset is $0$, validating its index as $0$.

Accessing elements in an array is highly efficient, allowing us to randomly access any element in $O(1)$ time.

Expand All @@ -135,7 +135,7 @@ Accessing elements in an array is highly efficient, allowing us to randomly acce

### Inserting elements

Array elements are tightly packed in memory, with no space available to accommodate additional data between them. Illustrated in Figure below, inserting an element in the middle of an array requires shifting all subsequent elements back by one position to create room for the new element.
Array elements are tightly packed in memory, with no space available to accommodate additional data between them. As illustrated in the figure below, inserting an element in the middle of an array requires shifting all subsequent elements back by one position to create room for the new element.

![Array element insertion example](array.assets/array_insert_element.png)

Expand Down
10 changes: 5 additions & 5 deletions en/docs/chapter_array_and_linkedlist/linked_list.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

Memory space is a shared resource among all programs. In a complex system environment, available memory can be dispersed throughout the memory space. We understand that the memory allocated for an array must be continuous. However, for very large arrays, finding a sufficiently large contiguous memory space might be challenging. This is where the flexible advantage of linked lists becomes evident.

A "linked list" is a linear data structure in which each element is a node object, and the nodes are interconnected through "references". These references hold the memory addresses of subsequent nodes, enabling navigation from one node to the next.
A <u>linked list</u> is a linear data structure in which each element is a node object, and the nodes are interconnected through "references". These references hold the memory addresses of subsequent nodes, enabling navigation from one node to the next.

The design of linked lists allows for their nodes to be distributed across memory locations without requiring contiguous memory addresses.

![Linked list definition and storage method](linked_list.assets/linkedlist_definition.png)

As shown in the figure, we see that the basic building block of a linked list is the "node" object. Each node comprises two key components: the node's "value" and a "reference" to the next node.
As shown in the figure above, we see that the basic building block of a linked list is the <u>node</u> object. Each node comprises two key components: the node's "value" and a "reference" to the next node.

- The first node in a linked list is the "head node", and the final one is the "tail node".
- The tail node points to "null", designated as `null` in Java, `nullptr` in C++, and `None` in Python.
Expand Down Expand Up @@ -406,7 +406,7 @@ The array as a whole is a variable, for instance, the array `nums` includes elem

### Inserting nodes

Inserting a node into a linked list is very easy. As shown in the figure, let's assume we aim to insert a new node `P` between two adjacent nodes `n0` and `n1`. **This can be achieved by simply modifying two node references (pointers)**, with a time complexity of $O(1)$.
Inserting a node into a linked list is very easy. As shown in the figure below, let's assume we aim to insert a new node `P` between two adjacent nodes `n0` and `n1`. **This can be achieved by simply modifying two node references (pointers)**, with a time complexity of $O(1)$.

By comparison, inserting an element into an array has a time complexity of $O(n)$, which becomes less efficient when dealing with large data volumes.

Expand All @@ -418,7 +418,7 @@ By comparison, inserting an element into an array has a time complexity of $O(n)

### Deleting nodes

As shown in the figure, deleting a node from a linked list is also very easy, **involving only the modification of a single node's reference (pointer)**.
As shown in the figure below, deleting a node from a linked list is also very easy, **involving only the modification of a single node's reference (pointer)**.

It's important to note that even though node `P` continues to point to `n1` after being deleted, it becomes inaccessible during linked list traversal. This effectively means that `P` is no longer a part of the linked list.

Expand Down Expand Up @@ -461,7 +461,7 @@ The table below summarizes the characteristics of arrays and linked lists, and i

## Common types of linked lists

As shown in the figure, there are three common types of linked lists.
As shown in the figure below, there are three common types of linked lists.

- **Singly linked list**: This is the standard linked list described earlier. Nodes in a singly linked list include a value and a reference to the next node. The first node is known as the head node, and the last node, which points to null (`None`), is the tail node.
- **Circular linked list**: This is formed when the tail node of a singly linked list points back to the head node, creating a loop. In a circular linked list, any node can function as the head node.
Expand Down
4 changes: 2 additions & 2 deletions en/docs/chapter_array_and_linkedlist/list.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# List

A "list" is an abstract data structure concept that represents an ordered collection of elements, supporting operations such as element access, modification, addition, deletion, and traversal, without requiring users to consider capacity limitations. Lists can be implemented based on linked lists or arrays.
A <u>list</u> is an abstract data structure concept that represents an ordered collection of elements, supporting operations such as element access, modification, addition, deletion, and traversal, without requiring users to consider capacity limitations. Lists can be implemented based on linked lists or arrays.

- A linked list inherently serves as a list, supporting operations for adding, deleting, searching, and modifying elements, with the flexibility to dynamically adjust its size.
- Arrays also support these operations, but due to their immutable length, they can be considered as a list with a length limit.

When implementing lists using arrays, **the immutability of length reduces the practicality of the list**. This is because predicting the amount of data to be stored in advance is often challenging, making it difficult to choose an appropriate list length. If the length is too small, it may not meet the requirements; if too large, it may waste memory space.

To solve this problem, we can implement lists using a "dynamic array." It inherits the advantages of arrays and can dynamically expand during program execution.
To solve this problem, we can implement lists using a <u>dynamic array</u>. It inherits the advantages of arrays and can dynamically expand during program execution.

In fact, **many programming languages' standard libraries implement lists using dynamic arrays**, such as Python's `list`, Java's `ArrayList`, C++'s `vector`, and C#'s `List`. In the following discussion, we will consider "list" and "dynamic array" as synonymous concepts.

Expand Down
Loading

0 comments on commit c4a7966

Please sign in to comment.