mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-10 06:26:08 +00:00
Translate all code to English (#1836)
* Review the EN heading format. * Fix pythontutor headings. * Fix pythontutor headings. * bug fixes * Fix headings in **/summary.md * Revisit the CN-to-EN translation for Python code using Claude-4.5 * Revisit the CN-to-EN translation for Java code using Claude-4.5 * Revisit the CN-to-EN translation for Cpp code using Claude-4.5. * Fix the dictionary. * Fix cpp code translation for the multipart strings. * Translate Go code to English. * Update workflows to test EN code. * Add EN translation for C. * Add EN translation for CSharp. * Add EN translation for Swift. * Trigger the CI check. * Revert. * Update en/hash_map.md * Add the EN version of Dart code. * Add the EN version of Kotlin code. * Add missing code files. * Add the EN version of JavaScript code. * Add the EN version of TypeScript code. * Fix the workflows. * Add the EN version of Ruby code. * Add the EN version of Rust code. * Update the CI check for the English version code. * Update Python CI check. * Fix cmakelists for en/C code. * Fix Ruby comments
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# Characteristics of dynamic programming problems
|
||||
# Characteristics of Dynamic Programming Problems
|
||||
|
||||
In the previous section, we learned how dynamic programming solves the original problem by decomposing it into subproblems. In fact, subproblem decomposition is a general algorithmic approach, with different emphases in divide and conquer, dynamic programming, and backtracking.
|
||||
|
||||
@@ -8,7 +8,7 @@ In the previous section, we learned how dynamic programming solves the original
|
||||
|
||||
In fact, dynamic programming is commonly used to solve optimization problems, which not only contain overlapping subproblems but also have two other major characteristics: optimal substructure and no aftereffects.
|
||||
|
||||
## Optimal substructure
|
||||
## Optimal Substructure
|
||||
|
||||
We make a slight modification to the stair climbing problem to make it more suitable for demonstrating the concept of optimal substructure.
|
||||
|
||||
@@ -48,7 +48,7 @@ This problem can also be space-optimized, compressing from one dimension to zero
|
||||
[file]{min_cost_climbing_stairs_dp}-[class]{}-[func]{min_cost_climbing_stairs_dp_comp}
|
||||
```
|
||||
|
||||
## No aftereffects
|
||||
## No Aftereffects
|
||||
|
||||
No aftereffects is one of the important characteristics that enable dynamic programming to solve problems effectively. Its definition is: **given a certain state, its future development is only related to the current state and has nothing to do with all past states**.
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
# Dynamic programming problem-solving approach
|
||||
# Dynamic Programming Problem-Solving Approach
|
||||
|
||||
The previous two sections introduced the main characteristics of dynamic programming problems. Next, let us explore two more practical issues together.
|
||||
|
||||
1. How to determine whether a problem is a dynamic programming problem?
|
||||
2. What is the complete process for solving a dynamic programming problem, and where should we start?
|
||||
|
||||
## Problem determination
|
||||
## Problem Determination
|
||||
|
||||
Generally speaking, if a problem contains overlapping subproblems, optimal substructure, and satisfies no aftereffects, then it is usually suitable for solving with dynamic programming. However, it is difficult to directly extract these characteristics from the problem description. Therefore, we usually relax the conditions and **first observe whether the problem is suitable for solving with backtracking (exhaustive search)**.
|
||||
|
||||
@@ -25,7 +25,7 @@ Correspondingly, there are also some "penalty points".
|
||||
|
||||
If a problem satisfies the decision tree model and has relatively obvious "bonus points", we can assume it is a dynamic programming problem and verify it during the solving process.
|
||||
|
||||
## Problem-solving steps
|
||||
## Problem-Solving Steps
|
||||
|
||||
The problem-solving process for dynamic programming varies depending on the nature and difficulty of the problem, but generally follows these steps: describe decisions, define states, establish the $dp$ table, derive state transition equations, determine boundary conditions, etc.
|
||||
|
||||
@@ -89,7 +89,7 @@ As shown in the figure below, since each cell is transferred from the cell to it
|
||||
|
||||
Based on the above analysis, we can directly write the dynamic programming code. However, subproblem decomposition is a top-down approach, so implementing in the order "brute force search $\rightarrow$ memoization $\rightarrow$ dynamic programming" is more aligned with thinking habits.
|
||||
|
||||
### Method 1: Brute force search
|
||||
### Method 1: Brute Force Search
|
||||
|
||||
Starting from state $[i, j]$, continuously decompose into smaller states $[i-1, j]$ and $[i, j-1]$. The recursive function includes the following elements.
|
||||
|
||||
@@ -124,7 +124,7 @@ As shown in the figure below, after introducing memoization, all subproblem solu
|
||||
|
||||

|
||||
|
||||
### Method 3: Dynamic programming
|
||||
### Method 3: Dynamic Programming
|
||||
|
||||
Implement the dynamic programming solution based on iteration, as shown in the code below:
|
||||
|
||||
@@ -172,7 +172,7 @@ The array `dp` has size $n \times m$, **thus the space complexity is $O(nm)$**.
|
||||
=== "<12>"
|
||||

|
||||
|
||||
### Space optimization
|
||||
### Space Optimization
|
||||
|
||||
Since each cell is only related to the cell to its left and the cell above it, we can use a single-row array to implement the $dp$ table.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Edit distance problem
|
||||
# Edit Distance Problem
|
||||
|
||||
Edit distance, also known as Levenshtein distance, refers to the minimum number of edits required to transform one string into another, commonly used in information retrieval and natural language processing to measure the similarity between two sequences.
|
||||
|
||||
@@ -20,7 +20,7 @@ From the perspective of the decision tree, the goal of this problem is to find t
|
||||
|
||||

|
||||
|
||||
### Dynamic programming approach
|
||||
### Dynamic Programming Approach
|
||||
|
||||
**Step 1: Think about the decisions in each round, define the state, and thus obtain the $dp$ table**
|
||||
|
||||
@@ -65,7 +65,7 @@ When both strings are empty, the number of edit steps is $0$, i.e., $dp[0, 0] =
|
||||
|
||||
Observing the state transition equation, the solution $dp[i, j]$ depends on solutions to the left, above, and upper-left, so the entire $dp$ table can be traversed in order through two nested loops.
|
||||
|
||||
### Code implementation
|
||||
### Code Implementation
|
||||
|
||||
```src
|
||||
[file]{edit_distance}-[class]{}-[func]{edit_distance_dp}
|
||||
@@ -118,7 +118,7 @@ As shown in the figure below, the state transition process for the edit distance
|
||||
=== "<15>"
|
||||

|
||||
|
||||
### Space optimization
|
||||
### Space Optimization
|
||||
|
||||
Since $dp[i, j]$ is transferred from the solutions above $dp[i-1, j]$, to the left $dp[i, j-1]$, and to the upper-left $dp[i-1, j-1]$, forward traversal will lose the upper-left solution $dp[i-1, j-1]$, and reverse traversal cannot build $dp[i, j-1]$ in advance, so neither traversal order is feasible.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Dynamic programming
|
||||
# Dynamic Programming
|
||||
|
||||

|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Introduction to dynamic programming
|
||||
# Introduction to Dynamic Programming
|
||||
|
||||
<u>Dynamic programming</u> is an important algorithmic paradigm that decomposes a problem into a series of smaller subproblems and avoids redundant computation by storing the solutions to subproblems, thereby significantly improving time efficiency.
|
||||
|
||||
@@ -18,7 +18,7 @@ The goal of this problem is to find the number of ways, **we can consider using
|
||||
[file]{climbing_stairs_backtrack}-[class]{}-[func]{climbing_stairs_backtrack}
|
||||
```
|
||||
|
||||
## Method 1: Brute force search
|
||||
## Method 1: Brute Force Search
|
||||
|
||||
Backtracking algorithms typically do not explicitly decompose problems, but rather treat solving the problem as a series of decision steps, searching for all possible solutions through trial and pruning.
|
||||
|
||||
@@ -73,7 +73,7 @@ Observe the figure below, **after memoization, all overlapping subproblems only
|
||||
|
||||

|
||||
|
||||
## Method 3: Dynamic programming
|
||||
## Method 3: Dynamic Programming
|
||||
|
||||
**Memoization is a "top-down" method**: we start from the original problem (root node), recursively decompose larger subproblems into smaller ones, until reaching the smallest known subproblems (leaf nodes). Afterward, by backtracking, we collect the solutions to the subproblems layer by layer to construct the solution to the original problem.
|
||||
|
||||
@@ -97,7 +97,7 @@ Based on the above content, we can summarize the commonly used terminology in dy
|
||||
- The states corresponding to the smallest subproblems (the $1$st and $2$nd steps) are called <u>initial states</u>.
|
||||
- The recurrence formula $dp[i] = dp[i-1] + dp[i-2]$ is called the <u>state transition equation</u>.
|
||||
|
||||
## Space optimization
|
||||
## Space Optimization
|
||||
|
||||
Observant readers may have noticed that **since $dp[i]$ is only related to $dp[i-1]$ and $dp[i-2]$, we do not need to use an array `dp` to store the solutions to all subproblems**, but can simply use two variables to roll forward. The code is as follows:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# 0-1 knapsack problem
|
||||
# 0-1 Knapsack Problem
|
||||
|
||||
The knapsack problem is an excellent introductory problem for dynamic programming and is one of the most common problem forms in dynamic programming. It has many variants, such as the 0-1 knapsack problem, the unbounded knapsack problem, and the multiple knapsack problem.
|
||||
|
||||
@@ -47,7 +47,7 @@ The current state $[i, c]$ is transferred from the state above $[i-1, c]$ and th
|
||||
|
||||
Based on the above analysis, we will next implement the brute force search, memoization, and dynamic programming solutions in order.
|
||||
|
||||
### Method 1: Brute force search
|
||||
### Method 1: Brute Force Search
|
||||
|
||||
The search code includes the following elements.
|
||||
|
||||
@@ -80,7 +80,7 @@ The figure below shows the search branches pruned in memoization.
|
||||
|
||||

|
||||
|
||||
### Method 3: Dynamic programming
|
||||
### Method 3: Dynamic Programming
|
||||
|
||||
Dynamic programming is essentially the process of filling the $dp$ table during state transitions. The code is as follows:
|
||||
|
||||
@@ -132,7 +132,7 @@ As shown in the figure below, both time complexity and space complexity are dete
|
||||
=== "<14>"
|
||||

|
||||
|
||||
### Space optimization
|
||||
### Space Optimization
|
||||
|
||||
Since each state is only related to the state in the row above it, we can use two arrays rolling forward to reduce the space complexity from $O(n^2)$ to $O(n)$.
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
# Summary
|
||||
|
||||
### Key Review
|
||||
|
||||
- Dynamic programming decomposes problems and avoids redundant computation by storing the solutions to subproblems, thereby significantly improving computational efficiency.
|
||||
- Without considering time constraints, all dynamic programming problems can be solved using backtracking (brute force search), but the recursion tree contains a large number of overlapping subproblems, resulting in extremely low efficiency. By introducing a memo list, we can store the solutions to all computed subproblems, ensuring that overlapping subproblems are only computed once.
|
||||
- Memoization is a top-down recursive solution, while the corresponding dynamic programming is a bottom-up iterative solution, similar to "filling in a table". Since the current state only depends on certain local states, we can eliminate one dimension of the $dp$ table to reduce space complexity.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Unbounded knapsack problem
|
||||
# Unbounded Knapsack Problem
|
||||
|
||||
In this section, we first solve another common knapsack problem: the unbounded knapsack, and then explore a special case of it: the coin change problem.
|
||||
|
||||
## Unbounded knapsack problem
|
||||
## Unbounded Knapsack Problem
|
||||
|
||||
!!! question
|
||||
|
||||
@@ -10,7 +10,7 @@ In this section, we first solve another common knapsack problem: the unbounded k
|
||||
|
||||

|
||||
|
||||
### Dynamic programming approach
|
||||
### Dynamic Programming Approach
|
||||
|
||||
The unbounded knapsack problem is very similar to the 0-1 knapsack problem, **differing only in that there is no limit on the number of times an item can be selected**.
|
||||
|
||||
@@ -28,7 +28,7 @@ $$
|
||||
dp[i, c] = \max(dp[i-1, c], dp[i, c - wgt[i-1]] + val[i-1])
|
||||
$$
|
||||
|
||||
### Code implementation
|
||||
### Code Implementation
|
||||
|
||||
Comparing the code for the two problems, there is one change in state transition from $i-1$ to $i$, with everything else identical:
|
||||
|
||||
@@ -36,7 +36,7 @@ Comparing the code for the two problems, there is one change in state transition
|
||||
[file]{unbounded_knapsack}-[class]{}-[func]{unbounded_knapsack_dp}
|
||||
```
|
||||
|
||||
### Space optimization
|
||||
### Space Optimization
|
||||
|
||||
Since the current state is transferred from states on the left and above, **after space optimization, each row in the $dp$ table should be traversed in forward order**.
|
||||
|
||||
@@ -66,7 +66,7 @@ The code implementation is relatively simple, just delete the first dimension of
|
||||
[file]{unbounded_knapsack}-[class]{}-[func]{unbounded_knapsack_dp_comp}
|
||||
```
|
||||
|
||||
## Coin change problem
|
||||
## Coin Change Problem
|
||||
|
||||
The knapsack problem represents a large class of dynamic programming problems and has many variants, such as the coin change problem.
|
||||
|
||||
@@ -76,7 +76,7 @@ The knapsack problem represents a large class of dynamic programming problems an
|
||||
|
||||

|
||||
|
||||
### Dynamic programming approach
|
||||
### Dynamic Programming Approach
|
||||
|
||||
**The coin change problem can be viewed as a special case of the unbounded knapsack problem**, with the following connections and differences.
|
||||
|
||||
@@ -107,7 +107,7 @@ When the target amount is $0$, the minimum number of coins needed to make it up
|
||||
|
||||
When there are no coins, **it is impossible to make up any amount $> 0$**, which is an invalid solution. To enable the $\min()$ function in the state transition equation to identify and filter out invalid solutions, we consider using $+ \infty$ to represent them, i.e., set all $dp[0, a]$ in the first row to $+ \infty$.
|
||||
|
||||
### Code implementation
|
||||
### Code Implementation
|
||||
|
||||
Most programming languages do not provide a $+ \infty$ variable, and can only use the maximum value of integer type `int` as a substitute. However, this can lead to large number overflow: the $+ 1$ operation in the state transition equation may cause overflow.
|
||||
|
||||
@@ -164,7 +164,7 @@ The figure below shows the dynamic programming process for coin change, which is
|
||||
=== "<15>"
|
||||

|
||||
|
||||
### Space optimization
|
||||
### Space Optimization
|
||||
|
||||
The space optimization for the coin change problem is handled in the same way as the unbounded knapsack problem:
|
||||
|
||||
@@ -172,7 +172,7 @@ The space optimization for the coin change problem is handled in the same way as
|
||||
[file]{coin_change}-[class]{}-[func]{coin_change_dp_comp}
|
||||
```
|
||||
|
||||
## Coin change problem II
|
||||
## Coin Change Problem Ii
|
||||
|
||||
!!! question
|
||||
|
||||
@@ -180,7 +180,7 @@ The space optimization for the coin change problem is handled in the same way as
|
||||
|
||||

|
||||
|
||||
### Dynamic programming approach
|
||||
### Dynamic Programming Approach
|
||||
|
||||
Compared to the previous problem, this problem's goal is to find the number of combinations, so the subproblem becomes: **the number of combinations among the first $i$ types of coins that can make up amount $a$**. The $dp$ table remains a two-dimensional matrix of size $(n+1) \times (amt + 1)$.
|
||||
|
||||
@@ -192,13 +192,13 @@ $$
|
||||
|
||||
When the target amount is $0$, no coins need to be selected to make up the target amount, so all $dp[i, 0]$ in the first column should be initialized to $1$. When there are no coins, it is impossible to make up any amount $>0$, so all $dp[0, a]$ in the first row equal $0$.
|
||||
|
||||
### Code implementation
|
||||
### Code Implementation
|
||||
|
||||
```src
|
||||
[file]{coin_change_ii}-[class]{}-[func]{coin_change_ii_dp}
|
||||
```
|
||||
|
||||
### Space optimization
|
||||
### Space Optimization
|
||||
|
||||
The space optimization is handled in the same way, just delete the coin dimension:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user