Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

translation: English Translation of the chapter of preface(part), introduction and complexity analysis(part) #994

Merged
merged 31 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
0aae500
Translate 1.0.0b6 release with the machine learning translator.
krahets Nov 1, 2023
a6fc570
Update Dockerfile
krahets Nov 1, 2023
44d9da8
Fix a badge logo.
krahets Nov 1, 2023
a172365
Fix EN translation of chapter_appendix/terminology.md (#913)
krahets Nov 2, 2023
ddec2de
Update README.md
krahets Nov 2, 2023
c82b2e7
Update README.md
krahets Nov 3, 2023
a0f140a
translation: Refined the automated translation of README (#932)
yuelinxin Nov 11, 2023
ef5cc29
translate: Embellish chapter_computational_complexity/index.md (#940)
Phoenix0415 Nov 13, 2023
abe55db
translation: Update chapter_computational_complexity/performance_eval…
Phoenix0415 Nov 15, 2023
77b7967
translation: Update terminology and improve readability in preface su…
longsizhuo Nov 21, 2023
22edeaa
Optimize the translation of
krahets Nov 21, 2023
3b7953c
Add .gitignore to Java subfolder.
krahets Nov 21, 2023
f0c4afe
Update the button assets.
krahets Dec 4, 2023
a7a6ef5
Fix the callout
krahets Dec 4, 2023
f4e64fe
translation: chapter_computational_complexity/summary to en (#953)
QiLOL Dec 7, 2023
c5f5abf
translation: chapter_introduction/what_is_dsa.md (#962)
krahets Dec 11, 2023
ac0e2bb
translation: chapter_introduction/summary.md (#963)
krahets Dec 21, 2023
bd8d47e
translation: Update README.md (#964)
krahets Dec 21, 2023
a8f0d89
translation: update space_complexity.md (#970)
thomasq0 Dec 21, 2023
41b6ba3
translation: Update chapter_introduction/index.md (#971)
K3v123 Dec 21, 2023
7b60f1e
translation: Update chapter_data_structure/classification_of_data_str…
yanedie Dec 21, 2023
4204130
translation: Update chapter_introduction/algorithms_are_everywhere.md…
K3v123 Dec 21, 2023
8fc28b2
Prepare merging into main branch.
krahets Dec 21, 2023
7dcb328
Update buttons
krahets Dec 21, 2023
6295161
Update Dockerfile
krahets Dec 21, 2023
305f88b
Merge branch 'main' into en
krahets Dec 21, 2023
108b909
Update index.md
krahets Dec 21, 2023
cda57c5
Update index.md
krahets Dec 21, 2023
f241711
Update README
krahets Dec 21, 2023
ad9ab29
Fix index.md
krahets Dec 21, 2023
bcc836f
Fix mkdocs-en.yml
krahets Dec 21, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
11 changes: 7 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,15 @@ RUN pip install mkdocs-material==9.4.1 mkdocs-glightbox

WORKDIR /hello-algo

COPY docs ./build/docs
COPY overrides ./build/overrides
COPY docs ./build/docs
COPY docs-en ./build/docs-en
COPY mkdocs.yml ./mkdocs.yml
COPY mkdocs-en.yml ./mkdocs-en.yml

RUN mkdocs build
RUN mkdocs build -f mkdocs.yml
RUN mkdocs build -f mkdocs-en.yml

WORKDIR /app/site
EXPOSE 8000

CMD ["mkdocs", "serve", "-a", "0.0.0.0:8000"]
CMD ["python", "-m", "http.server", "8000"]
87 changes: 87 additions & 0 deletions README-en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<p align="center">
<a href="https://www.hello-algo.com/en/">
<img src="https://www.hello-algo.com/en/index.assets/hello_algo_header.png" width="450">
</a>
</p>

<p align="center">
<img src="https://readme-typing-svg.demolab.com?font=Noto+Sans+SC&weight=500&duration=3500&pause=2000&color=21C8B8&center=true&vCenter=true&random=false&width=200&lines=Hello%2C+Algo+!" alt="hello-algo-typing-svg" />
</br>
Data Structures and Algorithms Crash Course with Animated Illustrations and Off-the-Shelf Code
</p>

<p align="center">
<a href="https://www.hello-algo.com/en/">
<img src="https://www.hello-algo.com/en/index.assets/btn_read_online_dark.svg" width="120"></a>
<a href="https://github.com/krahets/hello-algo/releases">
<img src="https://www.hello-algo.com/en/index.assets/btn_download_pdf_dark.svg" width="120"></a>
<a href="https://github.com/krahets/hello-algo">
<img src="https://www.hello-algo.com/en/index.assets/btn_chinese_edition_dark.svg" width="120"></a>
</p>

<p align="center">
<img src="https://www.hello-algo.com/en/index.assets/animation.gif" width="396">
<img src="https://www.hello-algo.com/en/index.assets/running_code.gif" width="396">
</p>

<p align="center">
<img src="https://img.shields.io/badge/Python-snow?logo=python&logoColor=3776AB">
<img src="https://img.shields.io/badge/C%2B%2B-snow?logo=c%2B%2B&logoColor=00599C">
<img src="https://img.shields.io/badge/Java-snow?logo=coffeescript&logoColor=FC4C02">
<img src="https://img.shields.io/badge/C%23-snow?logo=csharp&logoColor=512BD4">
<img src="https://img.shields.io/badge/Go-snow?logo=go&logoColor=00ADD8">
<img src="https://img.shields.io/badge/Swift-snow?logo=swift&logoColor=F05138">
<img src="https://img.shields.io/badge/JavaScript-snow?logo=javascript&logoColor=E9CE30">
<img src="https://img.shields.io/badge/TypeScript-snow?logo=typescript&logoColor=3178C6">
<img src="https://img.shields.io/badge/Dart-snow?logo=dart&logoColor=0175C2">
<img src="https://img.shields.io/badge/Rust-snow?logo=rust&logoColor=000000">
<img src="https://img.shields.io/badge/C-snow?logo=c&logoColor=A8B9CC">
<img src="https://img.shields.io/badge/Zig-snow?logo=zig&logoColor=F7A41D">
<img src="https://img.shields.io/badge/Stay%20Tuned-snow">
</p>

> [!Important]
>
> We are working on Chinese-to-English translation. For more information please see [#914](https://github.com/krahets/hello-algo/issues/914).

## About

This open-source project aims to create a free and beginner-friendly crash course for data structures and algorithms.

- Animated illustrations, easy-to-understand content, and a smooth learning curve help beginners explore the "knowledge map" of data structures and algorithms.
- Run code with just one click, helping readers improve their programming skills and understand the working principle of algorithms and the underlying implementation of data structures.
- We encourage readers to help each other. Questions and comments are usually replied to within two days.

If you find this book helpful, please give it a Star :star: to support us, thank you!

## Endorsements

> "An easy-to-understand book on data structures and algorithms, which guides readers to learn by minds-on and hands-on. Strongly recommended for algorithm beginners!"
>
> **—— Junhui Deng, Professor of Computer Science, Tsinghua University**

> "If I had 'Hello Algo' when I was learning data structures and algorithms, it would have been 10 times easier!"
>
> **—— Mu Li, Senior Principal Scientist, Amazon**

## Contribution

This open-source book is continuously being updated, and we welcome your participation in this project to provide better learning content for readers.

- [Content Correction](https://www.hello-algo.com/en/chapter_appendix/contribution/): Please help us correct or point out mistakes in the comments section such as grammatical errors, missing content, ambiguities, invalid links, or code bugs.
- [Code Transpilation](https://github.com/krahets/hello-algo/issues/15): We look forward to your contributions in various programming languages. We currently support 12 languages including Python, Java, C++, Go, and JavaScript.
- [Chinese-to-English](https://github.com/krahets/hello-algo/tree/en): We would love to invite you to join our translation team. The members are mainly from computer-science-related fields, English majors, and native English speakers.

We welcome your valuable suggestions and feedback. If you have any questions, please submit Issues or reach out via WeChat: `krahets-jyd`.

We would like to dedicate our thanks to all the contributors of this book. It is their selfless dedication that has made this book better. They are:

<p align="left">
<a href="https://github.com/krahets/hello-algo/graphs/contributors">
<img width="550" src="https://contrib.rocks/image?repo=krahets/hello-algo" />
</a>
</p>

## License

The texts, code, images, photos, and videos in this repository are licensed under [CC BY-NC-SA-4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/).
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
<img src="https://www.hello-algo.com/index.assets/btn_read_online_dark.svg" width="155"></a>
<a href="https://github.com/krahets/hello-algo/releases">
<img src="https://www.hello-algo.com/index.assets/btn_download_pdf_dark.svg" width="155"></a>
<a href="https://github.com/krahets/hello-algo/blob/master/README-en.md">
<img src="https://www.hello-algo.com/index.assets/btn_english_edition_dark.svg" width="155"></a>
</p>

<p align="center">
Expand Down
2 changes: 1 addition & 1 deletion codes/java/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
build
build
Binary file added docs-en/assets/covers/chapter_appendix.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_backtracking.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_data_structure.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_graph.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_greedy.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_hashing.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_heap.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_introduction.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_preface.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_searching.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_sorting.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs-en/assets/covers/chapter_tree.jpg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions docs-en/chapter_computational_complexity/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Complexity Analysis

<div class="center-table" markdown>

![complexity_analysis](../assets/covers/chapter_complexity_analysis.jpg)

</div>

!!! abstract

Complexity analysis is like a space-time guide in the vast universe of algorithms.

It leads us to explore deeply in the dimensions of time and space, in search of more elegant solutions.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
194 changes: 194 additions & 0 deletions docs-en/chapter_computational_complexity/iteration_and_recursion.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# Iteration vs. Recursion

In data structures and algorithms, it is common to repeat a task, which is closely related to the complexity of the algorithm. There are two basic program structures that we usually use to repeat a task: iteration and recursion.

## Iteration

An "iteration iteration" is a control structure that repeats a task. In iteration, a program repeats the execution of a piece of code until the condition is no longer satisfied.

### For Loops

`for` loops are one of the most common forms of iteration, **suitable when the number of iterations is known in advance**.

The following function implements the summation $1 + 2 + \dots + n$ based on a `for` loop, and the result is recorded using the variable `res`. Note that `range(a, b)` in Python corresponds to a "left-closed-right-open" interval, which is traversed in the range $a, a + 1, \dots, b-1$.

```src
[file]{iteration}-[class]{}-[func]{for_loop}
```

The figure below shows the flow block diagram of this summation function.

![Flow block diagram of the summation function](iteration_and_recursion.assets/iteration.png)

The number of operations in this summation function is proportional to the size of the input data $n$, or a "linear relationship". In fact, **time complexity describes this "linear relationship"**. This is described in more detail in the next section.

### While Loop

Similar to a `for` loop, a `while` loop is a way to implement iteration. In a `while` loop, the program first checks the condition at each turn, and if the condition is true, it continues, otherwise it ends the loop.

Below, we use a `while` loop to realize the summation $1 + 2 + \dots + n$ .

```src
[file]{iteration}-[class]{}-[func]{while_loop}
```

In `while` loops, since the steps of initializing and updating condition variables are independent of the loop structure, **it has more degrees of freedom than `for` loops**.

For example, in the following code, the condition variable $i$ is updated twice per round, which is not convenient to implement with a `for` loop.

```src
[file]{iteration}-[class]{}-[func]{while_loop_ii}
```

Overall, **`for` loops have more compact code and `while` loops are more flexible**, and both can implement iteration structures. The choice of which one to use should be based on the needs of the particular problem.

### Nested Loops

We can nest one loop structure inside another, using the `for` loop as an example:

```src
[file]{iteration}-[class]{}-[func]{nested_for_loop}
```

The figure below gives the block diagram of the flow of this nested loop.

![Block diagram of the flow of nested loops](iteration_and_recursion.assets/nested_iteration.png)

In this case, the number of operations of the function is proportional to $n^2$, or the algorithm's running time is "squared" to the size of the input data $n$.

We can continue to add nested loops, and each nest is a "dimension up", which will increase the time complexity to "cubic relations", "quadratic relations", and so on.

## Recursion

"Recursion recursion is an algorithmic strategy to solve a problem by calling the function itself. It consists of two main phases.

1. **recursive**: the program calls itself deeper and deeper, usually passing smaller or simpler arguments, until a "termination condition" is reached.
2. **Recursion**: After the "termination condition" is triggered, the program returns from the deepest level of the recursion function, level by level, aggregating the results of each level.

And from an implementation point of view, recursion code contains three main elements.

1. **Termination condition**: used to decide when to switch from "recursive" to "inductive".
2. **Recursion call**: corresponds to "recursion", where the function calls itself, usually with smaller or more simplified input parameters.
3. **return result**: corresponds to "return", returning the result of the current recursion level to the previous one.

Observe the following code, we only need to call the function `recur(n)` , and the calculation of $1 + 2 + \dots + n$ is done:

```src
[file]{recursion}-[class]{}-[func]{recur}
```

The figure below shows the recursion of the function.

![Recursion process for the summation function](iteration_and_recursion.assets/recursion_sum.png)

Although iteration and recursion can yield the same results from a computational point of view, **they represent two completely different paradigms for thinking about and solving problems**.

- **Iteration**: solving problems "from the bottom up". Start with the most basic steps and repeat or add to them until the task is completed.
- **Recursion**: solving problems "from the top down". The original problem is broken down into smaller subproblems that have the same form as the original problem. Next, the subproblem continues to be broken down into smaller subproblems until it stops at the base case (the solution to the base case is known).

As an example of the above summation function, set the problem $f(n) = 1 + 2 + \dots + n$ .

- **Iteration**: the summation process is simulated in a loop, iterating from $1$ to $n$ and executing the summation operation in each round to find $f(n)$.
- **Recursion**: decompose the problem into subproblems $f(n) = n + f(n-1)$ and keep (recursively) decomposing until the base case $f(1) = 1$ terminates.

### Call The Stack

Each time a recursion function calls itself, the system allocates memory for the newly opened function to store local variables, call addresses, other information, and so on. This results in two things.

- The context data for a function is stored in an area of memory called "stack frame space" and is not freed until the function returns. As a result, **recursion is usually more memory-intensive than iteration**.
- Recursion calls to functions incur additional overhead. **Therefore recursion is usually less time efficient than loops**.

As shown in the figure below, before the termination condition is triggered, there are $n$ unreturned recursion functions at the same time, **with a recursion depth of $n$** .

![Recursion call depth](iteration_and_recursion.assets/recursion_sum_depth.png)

In practice, the depth of recursion allowed by a programming language is usually limited, and too deep a recursion may result in a stack overflow error.

### Tail Recursion

Interestingly, **if a function makes a recursion call only at the last step before returning**, the function can be optimized by the compiler or interpreter to be comparable to iteration in terms of space efficiency. This situation is called "tail recursion tail recursion".

- **Ordinary recursion**: when a function returns to a function at a higher level, it needs to continue executing the code, so the system needs to save the context of the previous call.
- **tail recursion**: the recursion call is the last operation before the function returns, which means that the function does not need to continue with other operations after returning to the previous level, so the system does not need to save the context of the previous function.

In the case of calculating $1 + 2 + \dots + n$, for example, we can implement tail recursion by setting the result variable `res` as a function parameter.

```src
[file]{recursion}-[class]{}-[func]{tail_recur}
```

The execution of tail recursion is shown in the figure below. Comparing normal recursion and tail recursion, the execution point of the summation operation is different.

- **Ordinary recursion**: the summing operation is performed during the "return" process, and the summing operation is performed again after returning from each level.
- **Tail recursion**: the summing operation is performed in a "recursion" process, the "recursion" process simply returns in levels.

![tail recursion process](iteration_and_recursion.assets/tail_recursion_sum.png)

!!! tip

Note that many compilers or interpreters do not support tail recursion optimization. For example, Python does not support tail recursion optimization by default, so even if a function is tail recursive, you may still encounter stack overflow problems.

### Recursion Tree

When dealing with algorithmic problems related to divide and conquer, recursion is often more intuitive and easier to read than iteration. Take the Fibonacci sequence as an example.

!!! question

Given a Fibonacci series $0, 1, 1, 2, 3, 5, 8, 13, \dots$ , find the $n$th number of the series.

Let the $n$th number of the Fibonacci series be $f(n)$ , which leads to two easy conclusions.

- The first two numbers of the series are $f(1) = 0$ and $f(2) = 1$.
- Each number in the series is the sum of the previous two numbers, i.e. $f(n) = f(n - 1) + f(n - 2)$ .

Recursion code can be written by making recursion calls according to the recursion relationship, using the first two numbers as termination conditions. Call `fib(n)` to get the $n$th number of the Fibonacci series.

```src
[file]{recursion}-[class]{}-[func]{fib}
```

Looking at the above code, we have recursively called two functions within a function, **this means that from one call, two call branches are created**. As shown in the figure below, this recursion will result in a recursion tree with the number of levels $n$.

![Recursion tree for Fibonacci series](iteration_and_recursion.assets/recursion_tree.png)

Essentially, recursion embodies the paradigm of "breaking down a problem into smaller sub-problems", and this divide and conquer strategy is essential.

- From an algorithmic point of view, many important algorithmic strategies such as searching, sorting algorithm, backtracking, divide and conquer, dynamic programming, etc. directly or indirectly apply this way of thinking.
- From a data structure point of view, recursion is naturally suited to problems related to linked lists, trees and graphs because they are well suited to be analyzed with the idea of partitioning.

## Compare The Two

To summarize the above, as shown in the table below, iteration and recursion differ in implementation, performance and applicability.

<p align="center"> Table <id> &nbsp; Comparison of iteration and recursion features </p>

| | iteration | recursion |
| ------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| implementation | circular structure | function call itself |
| time-efficient | typically efficient, no function call overhead | overhead on every function call |
| Memory Usage | Usually uses a fixed size of memory space | Cumulative function calls may use a lot of stack frame space |
| Applicable Problems | For simple cyclic tasks, code is intuitive and readable | For sub-problem decomposition, such as trees, graphs, divide and conquer, backtracking, etc., the code structure is concise and clear |

!!! tip

If you find the following solutions difficult to understand, you can review them after reading the "Stack" chapter.

So what is the intrinsic connection between iteration and recursion? In the case of the recursive function described above, the summing operation takes place in the "return" phase of the recursion. This means that the function that is initially called is actually the last to complete its summing operation, **This mechanism works in the same way as the stack's "first in, last out" principle**.

In fact, recursion terms like "call stack" and "stack frame space" already imply a close relationship between recursion and the stack.

1. **Recursive**: When a function is called, the system allocates a new stack frame on the "call stack" for the function, which is used to store the function's local variables, parameters, return address, and other data.
2. **Return to**: When a function completes execution and returns, the corresponding stack frame is removed from the "call stack", restoring the function's previous execution environment.

Thus, **we can use an explicit stack to model the behavior of the call stack**, thus transforming recursion into an iteration form:

```src
[file]{recursion}-[class]{}-[func]{for_loop_recur}
```

Observing the code above, it becomes more complex when recursion is converted to iteration. Although iteration and recursion can be converted to each other in many cases, it is not always worth doing so for two reasons.

- The transformed code may be more difficult to understand and less readable.
- For some complex problems, simulating the behavior of the system call stack can be very difficult.

In short, **the choice of iteration or recursion depends on the nature of the particular problem**. In programming practice, it is crucial to weigh the advantages and disadvantages of both and choose the appropriate method based on the context.