mirror of
https://github.com/krahets/hello-algo.git
synced 2026-04-05 11:41:22 +08:00
Sort the coding languages by applications. (#721)
This commit is contained in:
@@ -34,10 +34,10 @@ $$
|
||||
|
||||
根据状态转移方程,以及初始状态 $dp[1] = cost[1]$ 和 $dp[2] = cost[2]$ ,我们就可以得到动态规划代码。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="min_cost_climbing_stairs_dp.java"
|
||||
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDP}
|
||||
```python title="min_cost_climbing_stairs_dp.py"
|
||||
[class]{}-[func]{min_cost_climbing_stairs_dp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -46,10 +46,16 @@ $$
|
||||
[class]{}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="min_cost_climbing_stairs_dp.py"
|
||||
[class]{}-[func]{min_cost_climbing_stairs_dp}
|
||||
```java title="min_cost_climbing_stairs_dp.java"
|
||||
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_cost_climbing_stairs_dp.cs"
|
||||
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -58,6 +64,12 @@ $$
|
||||
[class]{}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_cost_climbing_stairs_dp.swift"
|
||||
[class]{}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="min_cost_climbing_stairs_dp.js"
|
||||
@@ -70,30 +82,6 @@ $$
|
||||
[class]{}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_cost_climbing_stairs_dp.c"
|
||||
[class]{}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_cost_climbing_stairs_dp.cs"
|
||||
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_cost_climbing_stairs_dp.swift"
|
||||
[class]{}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_cost_climbing_stairs_dp.zig"
|
||||
[class]{}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="min_cost_climbing_stairs_dp.dart"
|
||||
@@ -106,16 +94,28 @@ $$
|
||||
[class]{}-[func]{min_cost_climbing_stairs_dp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_cost_climbing_stairs_dp.c"
|
||||
[class]{}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_cost_climbing_stairs_dp.zig"
|
||||
[class]{}-[func]{minCostClimbingStairsDP}
|
||||
```
|
||||
|
||||
下图展示了以上代码的动态规划过程。
|
||||
|
||||

|
||||
|
||||
本题也可以进行空间优化,将一维压缩至零维,使得空间复杂度从 $O(n)$ 降低至 $O(1)$ 。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="min_cost_climbing_stairs_dp.java"
|
||||
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDPComp}
|
||||
```python title="min_cost_climbing_stairs_dp.py"
|
||||
[class]{}-[func]{min_cost_climbing_stairs_dp_comp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -124,10 +124,16 @@ $$
|
||||
[class]{}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="min_cost_climbing_stairs_dp.py"
|
||||
[class]{}-[func]{min_cost_climbing_stairs_dp_comp}
|
||||
```java title="min_cost_climbing_stairs_dp.java"
|
||||
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_cost_climbing_stairs_dp.cs"
|
||||
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -136,6 +142,12 @@ $$
|
||||
[class]{}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_cost_climbing_stairs_dp.swift"
|
||||
[class]{}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="min_cost_climbing_stairs_dp.js"
|
||||
@@ -148,30 +160,6 @@ $$
|
||||
[class]{}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_cost_climbing_stairs_dp.c"
|
||||
[class]{}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_cost_climbing_stairs_dp.cs"
|
||||
[class]{min_cost_climbing_stairs_dp}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_cost_climbing_stairs_dp.swift"
|
||||
[class]{}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_cost_climbing_stairs_dp.zig"
|
||||
[class]{}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="min_cost_climbing_stairs_dp.dart"
|
||||
@@ -184,6 +172,18 @@ $$
|
||||
[class]{}-[func]{min_cost_climbing_stairs_dp_comp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_cost_climbing_stairs_dp.c"
|
||||
[class]{}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_cost_climbing_stairs_dp.zig"
|
||||
[class]{}-[func]{minCostClimbingStairsDPComp}
|
||||
```
|
||||
|
||||
## 无后效性
|
||||
|
||||
无后效性是动态规划能够有效解决问题的重要特性之一,定义为:**给定一个确定的状态,它的未来发展只与当前状态有关,而与当前状态过去所经历过的所有状态无关**。
|
||||
@@ -222,10 +222,10 @@ $$
|
||||
|
||||
最终,返回 $dp[n, 1] + dp[n, 2]$ 即可,两者之和代表爬到第 $n$ 阶的方案总数。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="climbing_stairs_constraint_dp.java"
|
||||
[class]{climbing_stairs_constraint_dp}-[func]{climbingStairsConstraintDP}
|
||||
```python title="climbing_stairs_constraint_dp.py"
|
||||
[class]{}-[func]{climbing_stairs_constraint_dp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -234,10 +234,16 @@ $$
|
||||
[class]{}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="climbing_stairs_constraint_dp.py"
|
||||
[class]{}-[func]{climbing_stairs_constraint_dp}
|
||||
```java title="climbing_stairs_constraint_dp.java"
|
||||
[class]{climbing_stairs_constraint_dp}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_constraint_dp.cs"
|
||||
[class]{climbing_stairs_constraint_dp}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -246,6 +252,12 @@ $$
|
||||
[class]{}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_constraint_dp.swift"
|
||||
[class]{}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="climbing_stairs_constraint_dp.js"
|
||||
@@ -258,30 +270,6 @@ $$
|
||||
[class]{}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_constraint_dp.c"
|
||||
[class]{}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_constraint_dp.cs"
|
||||
[class]{climbing_stairs_constraint_dp}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_constraint_dp.swift"
|
||||
[class]{}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_constraint_dp.zig"
|
||||
[class]{}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="climbing_stairs_constraint_dp.dart"
|
||||
@@ -294,6 +282,18 @@ $$
|
||||
[class]{}-[func]{climbing_stairs_constraint_dp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_constraint_dp.c"
|
||||
[class]{}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_constraint_dp.zig"
|
||||
[class]{}-[func]{climbingStairsConstraintDP}
|
||||
```
|
||||
|
||||
在上面的案例中,由于仅需多考虑前面一个状态,我们仍然可以通过扩展状态定义,使得问题重新满足无后效性。然而,某些问题具有非常严重的“有后效性”。
|
||||
|
||||
!!! question "爬楼梯与障碍生成"
|
||||
|
||||
@@ -98,10 +98,10 @@ $$
|
||||
- **终止条件**:当 $i = 0$ 且 $j = 0$ 时,返回代价 $grid[0, 0]$ 。
|
||||
- **剪枝**:当 $i < 0$ 时或 $j < 0$ 时索引越界,此时返回代价 $+\infty$ ,代表不可行。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="min_path_sum.java"
|
||||
[class]{min_path_sum}-[func]{minPathSumDFS}
|
||||
```python title="min_path_sum.py"
|
||||
[class]{}-[func]{min_path_sum_dfs}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -110,10 +110,16 @@ $$
|
||||
[class]{}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="min_path_sum.py"
|
||||
[class]{}-[func]{min_path_sum_dfs}
|
||||
```java title="min_path_sum.java"
|
||||
[class]{min_path_sum}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_path_sum.cs"
|
||||
[class]{min_path_sum}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -122,6 +128,12 @@ $$
|
||||
[class]{}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_path_sum.swift"
|
||||
[class]{}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="min_path_sum.js"
|
||||
@@ -134,30 +146,6 @@ $$
|
||||
[class]{}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_path_sum.c"
|
||||
[class]{}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_path_sum.cs"
|
||||
[class]{min_path_sum}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_path_sum.swift"
|
||||
[class]{}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_path_sum.zig"
|
||||
[class]{}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="min_path_sum.dart"
|
||||
@@ -170,6 +158,18 @@ $$
|
||||
[class]{}-[func]{min_path_sum_dfs}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_path_sum.c"
|
||||
[class]{}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_path_sum.zig"
|
||||
[class]{}-[func]{minPathSumDFS}
|
||||
```
|
||||
|
||||
下图给出了以 $dp[2, 1]$ 为根节点的递归树,其中包含一些重叠子问题,其数量会随着网格 `grid` 的尺寸变大而急剧增多。
|
||||
|
||||
本质上看,造成重叠子问题的原因为:**存在多条路径可以从左上角到达某一单元格**。
|
||||
@@ -182,10 +182,10 @@ $$
|
||||
|
||||
我们引入一个和网格 `grid` 相同尺寸的记忆列表 `mem` ,用于记录各个子问题的解,并将重叠子问题进行剪枝。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="min_path_sum.java"
|
||||
[class]{min_path_sum}-[func]{minPathSumDFSMem}
|
||||
```python title="min_path_sum.py"
|
||||
[class]{}-[func]{min_path_sum_dfs_mem}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -194,10 +194,16 @@ $$
|
||||
[class]{}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="min_path_sum.py"
|
||||
[class]{}-[func]{min_path_sum_dfs_mem}
|
||||
```java title="min_path_sum.java"
|
||||
[class]{min_path_sum}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_path_sum.cs"
|
||||
[class]{min_path_sum}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -206,6 +212,12 @@ $$
|
||||
[class]{}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_path_sum.swift"
|
||||
[class]{}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="min_path_sum.js"
|
||||
@@ -218,30 +230,6 @@ $$
|
||||
[class]{}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_path_sum.c"
|
||||
[class]{}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_path_sum.cs"
|
||||
[class]{min_path_sum}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_path_sum.swift"
|
||||
[class]{}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_path_sum.zig"
|
||||
[class]{}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="min_path_sum.dart"
|
||||
@@ -254,6 +242,18 @@ $$
|
||||
[class]{}-[func]{min_path_sum_dfs_mem}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_path_sum.c"
|
||||
[class]{}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_path_sum.zig"
|
||||
[class]{}-[func]{minPathSumDFSMem}
|
||||
```
|
||||
|
||||
如下图所示,在引入记忆化后,所有子问题的解只需计算一次,因此时间复杂度取决于状态总数,即网格尺寸 $O(nm)$ 。
|
||||
|
||||

|
||||
@@ -262,10 +262,10 @@ $$
|
||||
|
||||
基于迭代实现动态规划解法。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="min_path_sum.java"
|
||||
[class]{min_path_sum}-[func]{minPathSumDP}
|
||||
```python title="min_path_sum.py"
|
||||
[class]{}-[func]{min_path_sum_dp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -274,10 +274,16 @@ $$
|
||||
[class]{}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="min_path_sum.py"
|
||||
[class]{}-[func]{min_path_sum_dp}
|
||||
```java title="min_path_sum.java"
|
||||
[class]{min_path_sum}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_path_sum.cs"
|
||||
[class]{min_path_sum}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -286,6 +292,12 @@ $$
|
||||
[class]{}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_path_sum.swift"
|
||||
[class]{}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="min_path_sum.js"
|
||||
@@ -298,30 +310,6 @@ $$
|
||||
[class]{}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_path_sum.c"
|
||||
[class]{}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_path_sum.cs"
|
||||
[class]{min_path_sum}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_path_sum.swift"
|
||||
[class]{}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_path_sum.zig"
|
||||
[class]{}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="min_path_sum.dart"
|
||||
@@ -334,6 +322,18 @@ $$
|
||||
[class]{}-[func]{min_path_sum_dp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_path_sum.c"
|
||||
[class]{}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_path_sum.zig"
|
||||
[class]{}-[func]{minPathSumDP}
|
||||
```
|
||||
|
||||
下图展示了最小路径和的状态转移过程,其遍历了整个网格,**因此时间复杂度为 $O(nm)$** 。
|
||||
|
||||
数组 `dp` 大小为 $n \times m$ ,**因此空间复杂度为 $O(nm)$** 。
|
||||
@@ -380,10 +380,10 @@ $$
|
||||
|
||||
请注意,因为数组 `dp` 只能表示一行的状态,所以我们无法提前初始化首列状态,而是在遍历每行中更新它。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="min_path_sum.java"
|
||||
[class]{min_path_sum}-[func]{minPathSumDPComp}
|
||||
```python title="min_path_sum.py"
|
||||
[class]{}-[func]{min_path_sum_dp_comp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -392,10 +392,16 @@ $$
|
||||
[class]{}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="min_path_sum.py"
|
||||
[class]{}-[func]{min_path_sum_dp_comp}
|
||||
```java title="min_path_sum.java"
|
||||
[class]{min_path_sum}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_path_sum.cs"
|
||||
[class]{min_path_sum}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -404,6 +410,12 @@ $$
|
||||
[class]{}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_path_sum.swift"
|
||||
[class]{}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="min_path_sum.js"
|
||||
@@ -416,30 +428,6 @@ $$
|
||||
[class]{}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_path_sum.c"
|
||||
[class]{}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="min_path_sum.cs"
|
||||
[class]{min_path_sum}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="min_path_sum.swift"
|
||||
[class]{}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_path_sum.zig"
|
||||
[class]{}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="min_path_sum.dart"
|
||||
@@ -451,3 +439,15 @@ $$
|
||||
```rust title="min_path_sum.rs"
|
||||
[class]{}-[func]{min_path_sum_dp_comp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="min_path_sum.c"
|
||||
[class]{}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="min_path_sum.zig"
|
||||
[class]{}-[func]{minPathSumDPComp}
|
||||
```
|
||||
|
||||
@@ -67,10 +67,10 @@ $$
|
||||
|
||||
### 代码实现
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="edit_distance.java"
|
||||
[class]{edit_distance}-[func]{editDistanceDP}
|
||||
```python title="edit_distance.py"
|
||||
[class]{}-[func]{edit_distance_dp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -79,10 +79,16 @@ $$
|
||||
[class]{}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="edit_distance.py"
|
||||
[class]{}-[func]{edit_distance_dp}
|
||||
```java title="edit_distance.java"
|
||||
[class]{edit_distance}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="edit_distance.cs"
|
||||
[class]{edit_distance}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -91,6 +97,12 @@ $$
|
||||
[class]{}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="edit_distance.swift"
|
||||
[class]{}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="edit_distance.js"
|
||||
@@ -103,30 +115,6 @@ $$
|
||||
[class]{}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="edit_distance.c"
|
||||
[class]{}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="edit_distance.cs"
|
||||
[class]{edit_distance}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="edit_distance.swift"
|
||||
[class]{}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="edit_distance.zig"
|
||||
[class]{}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="edit_distance.dart"
|
||||
@@ -139,6 +127,18 @@ $$
|
||||
[class]{}-[func]{edit_distance_dp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="edit_distance.c"
|
||||
[class]{}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="edit_distance.zig"
|
||||
[class]{}-[func]{editDistanceDP}
|
||||
```
|
||||
|
||||
如下图所示,编辑距离问题的状态转移过程与背包问题非常类似,都可以看作是填写一个二维网格的过程。
|
||||
|
||||
=== "<1>"
|
||||
@@ -192,10 +192,10 @@ $$
|
||||
|
||||
为此,我们可以使用一个变量 `leftup` 来暂存左上方的解 $dp[i-1, j-1]$ ,从而只需考虑左方和上方的解。此时的情况与完全背包问题相同,可使用正序遍历。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="edit_distance.java"
|
||||
[class]{edit_distance}-[func]{editDistanceDPComp}
|
||||
```python title="edit_distance.py"
|
||||
[class]{}-[func]{edit_distance_dp_comp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -204,10 +204,16 @@ $$
|
||||
[class]{}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="edit_distance.py"
|
||||
[class]{}-[func]{edit_distance_dp_comp}
|
||||
```java title="edit_distance.java"
|
||||
[class]{edit_distance}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="edit_distance.cs"
|
||||
[class]{edit_distance}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -216,6 +222,12 @@ $$
|
||||
[class]{}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="edit_distance.swift"
|
||||
[class]{}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="edit_distance.js"
|
||||
@@ -228,30 +240,6 @@ $$
|
||||
[class]{}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="edit_distance.c"
|
||||
[class]{}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="edit_distance.cs"
|
||||
[class]{edit_distance}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="edit_distance.swift"
|
||||
[class]{}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="edit_distance.zig"
|
||||
[class]{}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="edit_distance.dart"
|
||||
@@ -263,3 +251,15 @@ $$
|
||||
```rust title="edit_distance.rs"
|
||||
[class]{}-[func]{edit_distance_dp_comp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="edit_distance.c"
|
||||
[class]{}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="edit_distance.zig"
|
||||
[class]{}-[func]{editDistanceDPComp}
|
||||
```
|
||||
|
||||
@@ -14,12 +14,12 @@
|
||||
|
||||
本题的目标是求解方案数量,**我们可以考虑通过回溯来穷举所有可能性**。具体来说,将爬楼梯想象为一个多轮选择的过程:从地面出发,每轮选择上 $1$ 阶或 $2$ 阶,每当到达楼梯顶部时就将方案数量加 $1$ ,当越过楼梯顶部时就将其剪枝。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="climbing_stairs_backtrack.java"
|
||||
[class]{climbing_stairs_backtrack}-[func]{backtrack}
|
||||
```python title="climbing_stairs_backtrack.py"
|
||||
[class]{}-[func]{backtrack}
|
||||
|
||||
[class]{climbing_stairs_backtrack}-[func]{climbingStairsBacktrack}
|
||||
[class]{}-[func]{climbing_stairs_backtrack}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -30,12 +30,20 @@
|
||||
[class]{}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="climbing_stairs_backtrack.py"
|
||||
[class]{}-[func]{backtrack}
|
||||
```java title="climbing_stairs_backtrack.java"
|
||||
[class]{climbing_stairs_backtrack}-[func]{backtrack}
|
||||
|
||||
[class]{}-[func]{climbing_stairs_backtrack}
|
||||
[class]{climbing_stairs_backtrack}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_backtrack.cs"
|
||||
[class]{climbing_stairs_backtrack}-[func]{backtrack}
|
||||
|
||||
[class]{climbing_stairs_backtrack}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -46,6 +54,14 @@
|
||||
[class]{}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_backtrack.swift"
|
||||
[class]{}-[func]{backtrack}
|
||||
|
||||
[class]{}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="climbing_stairs_backtrack.js"
|
||||
@@ -62,38 +78,6 @@
|
||||
[class]{}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_backtrack.c"
|
||||
[class]{}-[func]{backtrack}
|
||||
|
||||
[class]{}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_backtrack.cs"
|
||||
[class]{climbing_stairs_backtrack}-[func]{backtrack}
|
||||
|
||||
[class]{climbing_stairs_backtrack}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_backtrack.swift"
|
||||
[class]{}-[func]{backtrack}
|
||||
|
||||
[class]{}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_backtrack.zig"
|
||||
[class]{}-[func]{backtrack}
|
||||
|
||||
[class]{}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="climbing_stairs_backtrack.dart"
|
||||
@@ -110,6 +94,22 @@
|
||||
[class]{}-[func]{climbing_stairs_backtrack}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_backtrack.c"
|
||||
[class]{}-[func]{backtrack}
|
||||
|
||||
[class]{}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_backtrack.zig"
|
||||
[class]{}-[func]{backtrack}
|
||||
|
||||
[class]{}-[func]{climbingStairsBacktrack}
|
||||
```
|
||||
|
||||
## 方法一:暴力搜索
|
||||
|
||||
回溯算法通常并不显式地对问题进行拆解,而是将问题看作一系列决策步骤,通过试探和剪枝,搜索所有可能的解。
|
||||
@@ -136,12 +136,12 @@ $$
|
||||
|
||||
观察以下代码,它和标准回溯代码都属于深度优先搜索,但更加简洁。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="climbing_stairs_dfs.java"
|
||||
[class]{climbing_stairs_dfs}-[func]{dfs}
|
||||
```python title="climbing_stairs_dfs.py"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{climbing_stairs_dfs}-[func]{climbingStairsDFS}
|
||||
[class]{}-[func]{climbing_stairs_dfs}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -152,12 +152,20 @@ $$
|
||||
[class]{}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="climbing_stairs_dfs.py"
|
||||
[class]{}-[func]{dfs}
|
||||
```java title="climbing_stairs_dfs.java"
|
||||
[class]{climbing_stairs_dfs}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbing_stairs_dfs}
|
||||
[class]{climbing_stairs_dfs}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_dfs.cs"
|
||||
[class]{climbing_stairs_dfs}-[func]{dfs}
|
||||
|
||||
[class]{climbing_stairs_dfs}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -168,6 +176,14 @@ $$
|
||||
[class]{}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_dfs.swift"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="climbing_stairs_dfs.js"
|
||||
@@ -184,38 +200,6 @@ $$
|
||||
[class]{}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_dfs.c"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_dfs.cs"
|
||||
[class]{climbing_stairs_dfs}-[func]{dfs}
|
||||
|
||||
[class]{climbing_stairs_dfs}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_dfs.swift"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_dfs.zig"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="climbing_stairs_dfs.dart"
|
||||
@@ -232,6 +216,22 @@ $$
|
||||
[class]{}-[func]{climbing_stairs_dfs}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_dfs.c"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_dfs.zig"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFS}
|
||||
```
|
||||
|
||||
下图展示了暴力搜索形成的递归树。对于问题 $dp[n]$ ,其递归树的深度为 $n$ ,时间复杂度为 $O(2^n)$ 。指数阶属于爆炸式增长,如果我们输入一个比较大的 $n$ ,则会陷入漫长的等待之中。
|
||||
|
||||

|
||||
@@ -247,12 +247,12 @@ $$
|
||||
1. 当首次计算 $dp[i]$ 时,我们将其记录至 `mem[i]` ,以便之后使用。
|
||||
2. 当再次需要计算 $dp[i]$ 时,我们便可直接从 `mem[i]` 中获取结果,从而避免重复计算该子问题。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="climbing_stairs_dfs_mem.java"
|
||||
[class]{climbing_stairs_dfs_mem}-[func]{dfs}
|
||||
```python title="climbing_stairs_dfs_mem.py"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{climbing_stairs_dfs_mem}-[func]{climbingStairsDFSMem}
|
||||
[class]{}-[func]{climbing_stairs_dfs_mem}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -263,12 +263,20 @@ $$
|
||||
[class]{}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="climbing_stairs_dfs_mem.py"
|
||||
[class]{}-[func]{dfs}
|
||||
```java title="climbing_stairs_dfs_mem.java"
|
||||
[class]{climbing_stairs_dfs_mem}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbing_stairs_dfs_mem}
|
||||
[class]{climbing_stairs_dfs_mem}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_dfs_mem.cs"
|
||||
[class]{climbing_stairs_dfs_mem}-[func]{dfs}
|
||||
|
||||
[class]{climbing_stairs_dfs_mem}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -279,6 +287,14 @@ $$
|
||||
[class]{}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_dfs_mem.swift"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="climbing_stairs_dfs_mem.js"
|
||||
@@ -295,38 +311,6 @@ $$
|
||||
[class]{}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_dfs_mem.c"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_dfs_mem.cs"
|
||||
[class]{climbing_stairs_dfs_mem}-[func]{dfs}
|
||||
|
||||
[class]{climbing_stairs_dfs_mem}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_dfs_mem.swift"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_dfs_mem.zig"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="climbing_stairs_dfs_mem.dart"
|
||||
@@ -343,6 +327,22 @@ $$
|
||||
[class]{}-[func]{climbing_stairs_dfs_mem}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_dfs_mem.c"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_dfs_mem.zig"
|
||||
[class]{}-[func]{dfs}
|
||||
|
||||
[class]{}-[func]{climbingStairsDFSMem}
|
||||
```
|
||||
|
||||
观察下图,**经过记忆化处理后,所有重叠子问题都只需被计算一次,时间复杂度被优化至 $O(n)$** ,这是一个巨大的飞跃。
|
||||
|
||||

|
||||
@@ -355,10 +355,10 @@ $$
|
||||
|
||||
由于动态规划不包含回溯过程,因此只需使用循环迭代实现,无须使用递归。在以下代码中,我们初始化一个数组 `dp` 来存储子问题的解,它起到了记忆化搜索中数组 `mem` 相同的记录作用。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="climbing_stairs_dp.java"
|
||||
[class]{climbing_stairs_dp}-[func]{climbingStairsDP}
|
||||
```python title="climbing_stairs_dp.py"
|
||||
[class]{}-[func]{climbing_stairs_dp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -367,10 +367,16 @@ $$
|
||||
[class]{}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="climbing_stairs_dp.py"
|
||||
[class]{}-[func]{climbing_stairs_dp}
|
||||
```java title="climbing_stairs_dp.java"
|
||||
[class]{climbing_stairs_dp}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_dp.cs"
|
||||
[class]{climbing_stairs_dp}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -379,6 +385,12 @@ $$
|
||||
[class]{}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_dp.swift"
|
||||
[class]{}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="climbing_stairs_dp.js"
|
||||
@@ -391,30 +403,6 @@ $$
|
||||
[class]{}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_dp.c"
|
||||
[class]{}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_dp.cs"
|
||||
[class]{climbing_stairs_dp}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_dp.swift"
|
||||
[class]{}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_dp.zig"
|
||||
[class]{}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="climbing_stairs_dp.dart"
|
||||
@@ -427,6 +415,18 @@ $$
|
||||
[class]{}-[func]{climbing_stairs_dp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_dp.c"
|
||||
[class]{}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_dp.zig"
|
||||
[class]{}-[func]{climbingStairsDP}
|
||||
```
|
||||
|
||||
下图模拟了以上代码的执行过程。
|
||||
|
||||

|
||||
@@ -443,10 +443,10 @@ $$
|
||||
|
||||
细心的你可能发现,**由于 $dp[i]$ 只与 $dp[i-1]$ 和 $dp[i-2]$ 有关,因此我们无须使用一个数组 `dp` 来存储所有子问题的解**,而只需两个变量滚动前进即可。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="climbing_stairs_dp.java"
|
||||
[class]{climbing_stairs_dp}-[func]{climbingStairsDPComp}
|
||||
```python title="climbing_stairs_dp.py"
|
||||
[class]{}-[func]{climbing_stairs_dp_comp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -455,10 +455,16 @@ $$
|
||||
[class]{}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="climbing_stairs_dp.py"
|
||||
[class]{}-[func]{climbing_stairs_dp_comp}
|
||||
```java title="climbing_stairs_dp.java"
|
||||
[class]{climbing_stairs_dp}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_dp.cs"
|
||||
[class]{climbing_stairs_dp}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -467,6 +473,12 @@ $$
|
||||
[class]{}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_dp.swift"
|
||||
[class]{}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="climbing_stairs_dp.js"
|
||||
@@ -479,30 +491,6 @@ $$
|
||||
[class]{}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_dp.c"
|
||||
[class]{}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="climbing_stairs_dp.cs"
|
||||
[class]{climbing_stairs_dp}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="climbing_stairs_dp.swift"
|
||||
[class]{}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_dp.zig"
|
||||
[class]{}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="climbing_stairs_dp.dart"
|
||||
@@ -515,6 +503,18 @@ $$
|
||||
[class]{}-[func]{climbing_stairs_dp_comp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="climbing_stairs_dp.c"
|
||||
[class]{}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="climbing_stairs_dp.zig"
|
||||
[class]{}-[func]{climbingStairsDPComp}
|
||||
```
|
||||
|
||||
观察以上代码,由于省去了数组 `dp` 占用的空间,因此空间复杂度从 $O(n)$ 降低至 $O(1)$ 。
|
||||
|
||||
在动态规划问题中,当前状态往往仅与前面有限个状态有关,这时我们可以只保留必要的状态,通过“降维”来节省内存空间。**这种空间优化技巧被称为“滚动变量”或“滚动数组”**。
|
||||
|
||||
@@ -56,10 +56,10 @@ $$
|
||||
- **终止条件**:当物品编号越界 $i = 0$ 或背包剩余容量为 $0$ 时,终止递归并返回价值 $0$ 。
|
||||
- **剪枝**:若当前物品重量超出背包剩余容量,则只能不放入背包。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="knapsack.java"
|
||||
[class]{knapsack}-[func]{knapsackDFS}
|
||||
```python title="knapsack.py"
|
||||
[class]{}-[func]{knapsack_dfs}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -68,10 +68,16 @@ $$
|
||||
[class]{}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="knapsack.py"
|
||||
[class]{}-[func]{knapsack_dfs}
|
||||
```java title="knapsack.java"
|
||||
[class]{knapsack}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="knapsack.cs"
|
||||
[class]{knapsack}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -80,6 +86,12 @@ $$
|
||||
[class]{}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="knapsack.swift"
|
||||
[class]{}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="knapsack.js"
|
||||
@@ -92,30 +104,6 @@ $$
|
||||
[class]{}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="knapsack.c"
|
||||
[class]{}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="knapsack.cs"
|
||||
[class]{knapsack}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="knapsack.swift"
|
||||
[class]{}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="knapsack.zig"
|
||||
[class]{}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="knapsack.dart"
|
||||
@@ -128,6 +116,18 @@ $$
|
||||
[class]{}-[func]{knapsack_dfs}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="knapsack.c"
|
||||
[class]{}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="knapsack.zig"
|
||||
[class]{}-[func]{knapsackDFS}
|
||||
```
|
||||
|
||||
如下图所示,由于每个物品都会产生不选和选两条搜索分支,因此时间复杂度为 $O(2^n)$ 。
|
||||
|
||||
观察递归树,容易发现其中存在重叠子问题,例如 $dp[1, 10]$ 等。而当物品较多、背包容量较大,尤其是相同重量的物品较多时,重叠子问题的数量将会大幅增多。
|
||||
@@ -140,10 +140,10 @@ $$
|
||||
|
||||
引入记忆化之后,**时间复杂度取决于子问题数量**,也就是 $O(n \times cap)$ 。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="knapsack.java"
|
||||
[class]{knapsack}-[func]{knapsackDFSMem}
|
||||
```python title="knapsack.py"
|
||||
[class]{}-[func]{knapsack_dfs_mem}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -152,10 +152,16 @@ $$
|
||||
[class]{}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="knapsack.py"
|
||||
[class]{}-[func]{knapsack_dfs_mem}
|
||||
```java title="knapsack.java"
|
||||
[class]{knapsack}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="knapsack.cs"
|
||||
[class]{knapsack}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -164,6 +170,12 @@ $$
|
||||
[class]{}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="knapsack.swift"
|
||||
[class]{}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="knapsack.js"
|
||||
@@ -176,30 +188,6 @@ $$
|
||||
[class]{}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="knapsack.c"
|
||||
[class]{}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="knapsack.cs"
|
||||
[class]{knapsack}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="knapsack.swift"
|
||||
[class]{}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="knapsack.zig"
|
||||
[class]{}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="knapsack.dart"
|
||||
@@ -212,6 +200,18 @@ $$
|
||||
[class]{}-[func]{knapsack_dfs_mem}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="knapsack.c"
|
||||
[class]{}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="knapsack.zig"
|
||||
[class]{}-[func]{knapsackDFSMem}
|
||||
```
|
||||
|
||||
下图展示了在记忆化递归中被剪掉的搜索分支。
|
||||
|
||||

|
||||
@@ -220,10 +220,10 @@ $$
|
||||
|
||||
动态规划实质上就是在状态转移中填充 $dp$ 表的过程,代码如下所示。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="knapsack.java"
|
||||
[class]{knapsack}-[func]{knapsackDP}
|
||||
```python title="knapsack.py"
|
||||
[class]{}-[func]{knapsack_dp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -232,10 +232,16 @@ $$
|
||||
[class]{}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="knapsack.py"
|
||||
[class]{}-[func]{knapsack_dp}
|
||||
```java title="knapsack.java"
|
||||
[class]{knapsack}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="knapsack.cs"
|
||||
[class]{knapsack}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -244,6 +250,12 @@ $$
|
||||
[class]{}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="knapsack.swift"
|
||||
[class]{}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="knapsack.js"
|
||||
@@ -256,30 +268,6 @@ $$
|
||||
[class]{}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="knapsack.c"
|
||||
[class]{}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="knapsack.cs"
|
||||
[class]{knapsack}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="knapsack.swift"
|
||||
[class]{}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="knapsack.zig"
|
||||
[class]{}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="knapsack.dart"
|
||||
@@ -292,6 +280,18 @@ $$
|
||||
[class]{}-[func]{knapsack_dp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="knapsack.c"
|
||||
[class]{}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="knapsack.zig"
|
||||
[class]{}-[func]{knapsackDP}
|
||||
```
|
||||
|
||||
如下图所示,时间复杂度和空间复杂度都由数组 `dp` 大小决定,即 $O(n \times cap)$ 。
|
||||
|
||||
=== "<1>"
|
||||
@@ -367,10 +367,10 @@ $$
|
||||
|
||||
在代码实现中,我们仅需将数组 `dp` 的第一维 $i$ 直接删除,并且把内循环更改为倒序遍历即可。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="knapsack.java"
|
||||
[class]{knapsack}-[func]{knapsackDPComp}
|
||||
```python title="knapsack.py"
|
||||
[class]{}-[func]{knapsack_dp_comp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -379,10 +379,16 @@ $$
|
||||
[class]{}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="knapsack.py"
|
||||
[class]{}-[func]{knapsack_dp_comp}
|
||||
```java title="knapsack.java"
|
||||
[class]{knapsack}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="knapsack.cs"
|
||||
[class]{knapsack}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -391,6 +397,12 @@ $$
|
||||
[class]{}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="knapsack.swift"
|
||||
[class]{}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="knapsack.js"
|
||||
@@ -403,30 +415,6 @@ $$
|
||||
[class]{}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="knapsack.c"
|
||||
[class]{}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="knapsack.cs"
|
||||
[class]{knapsack}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="knapsack.swift"
|
||||
[class]{}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="knapsack.zig"
|
||||
[class]{}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="knapsack.dart"
|
||||
@@ -438,3 +426,15 @@ $$
|
||||
```rust title="knapsack.rs"
|
||||
[class]{}-[func]{knapsack_dp_comp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="knapsack.c"
|
||||
[class]{}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="knapsack.zig"
|
||||
[class]{}-[func]{knapsackDPComp}
|
||||
```
|
||||
|
||||
@@ -32,10 +32,10 @@ $$
|
||||
|
||||
对比两道题目的代码,状态转移中有一处从 $i-1$ 变为 $i$ ,其余完全一致。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="unbounded_knapsack.java"
|
||||
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDP}
|
||||
```python title="unbounded_knapsack.py"
|
||||
[class]{}-[func]{unbounded_knapsack_dp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -44,10 +44,16 @@ $$
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="unbounded_knapsack.py"
|
||||
[class]{}-[func]{unbounded_knapsack_dp}
|
||||
```java title="unbounded_knapsack.java"
|
||||
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="unbounded_knapsack.cs"
|
||||
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -56,6 +62,12 @@ $$
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="unbounded_knapsack.swift"
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="unbounded_knapsack.js"
|
||||
@@ -68,30 +80,6 @@ $$
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="unbounded_knapsack.c"
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="unbounded_knapsack.cs"
|
||||
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="unbounded_knapsack.swift"
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="unbounded_knapsack.zig"
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="unbounded_knapsack.dart"
|
||||
@@ -104,6 +92,18 @@ $$
|
||||
[class]{}-[func]{unbounded_knapsack_dp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="unbounded_knapsack.c"
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="unbounded_knapsack.zig"
|
||||
[class]{}-[func]{unboundedKnapsackDP}
|
||||
```
|
||||
|
||||
### 空间优化
|
||||
|
||||
由于当前状态是从左边和上边的状态转移而来,**因此空间优化后应该对 $dp$ 表中的每一行采取正序遍历**。
|
||||
@@ -130,10 +130,10 @@ $$
|
||||
|
||||
代码实现比较简单,仅需将数组 `dp` 的第一维删除。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="unbounded_knapsack.java"
|
||||
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDPComp}
|
||||
```python title="unbounded_knapsack.py"
|
||||
[class]{}-[func]{unbounded_knapsack_dp_comp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -142,10 +142,16 @@ $$
|
||||
[class]{}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="unbounded_knapsack.py"
|
||||
[class]{}-[func]{unbounded_knapsack_dp_comp}
|
||||
```java title="unbounded_knapsack.java"
|
||||
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="unbounded_knapsack.cs"
|
||||
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -154,6 +160,12 @@ $$
|
||||
[class]{}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="unbounded_knapsack.swift"
|
||||
[class]{}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="unbounded_knapsack.js"
|
||||
@@ -166,30 +178,6 @@ $$
|
||||
[class]{}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="unbounded_knapsack.c"
|
||||
[class]{}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="unbounded_knapsack.cs"
|
||||
[class]{unbounded_knapsack}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="unbounded_knapsack.swift"
|
||||
[class]{}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="unbounded_knapsack.zig"
|
||||
[class]{}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="unbounded_knapsack.dart"
|
||||
@@ -202,6 +190,18 @@ $$
|
||||
[class]{}-[func]{unbounded_knapsack_dp_comp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="unbounded_knapsack.c"
|
||||
[class]{}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="unbounded_knapsack.zig"
|
||||
[class]{}-[func]{unboundedKnapsackDPComp}
|
||||
```
|
||||
|
||||
## 零钱兑换问题
|
||||
|
||||
背包问题是一大类动态规划问题的代表,其拥有很多的变种,例如零钱兑换问题。
|
||||
@@ -251,10 +251,10 @@ $$
|
||||
|
||||
最后返回前,判断 $dp[n, amt]$ 是否等于 $amt + 1$ ,若是则返回 $-1$ ,代表无法凑出目标金额。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="coin_change.java"
|
||||
[class]{coin_change}-[func]{coinChangeDP}
|
||||
```python title="coin_change.py"
|
||||
[class]{}-[func]{coin_change_dp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -263,10 +263,16 @@ $$
|
||||
[class]{}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="coin_change.py"
|
||||
[class]{}-[func]{coin_change_dp}
|
||||
```java title="coin_change.java"
|
||||
[class]{coin_change}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="coin_change.cs"
|
||||
[class]{coin_change}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -275,6 +281,12 @@ $$
|
||||
[class]{}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="coin_change.swift"
|
||||
[class]{}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="coin_change.js"
|
||||
@@ -287,30 +299,6 @@ $$
|
||||
[class]{}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="coin_change.c"
|
||||
[class]{}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="coin_change.cs"
|
||||
[class]{coin_change}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="coin_change.swift"
|
||||
[class]{}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="coin_change.zig"
|
||||
[class]{}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="coin_change.dart"
|
||||
@@ -323,6 +311,18 @@ $$
|
||||
[class]{}-[func]{coin_change_dp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="coin_change.c"
|
||||
[class]{}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="coin_change.zig"
|
||||
[class]{}-[func]{coinChangeDP}
|
||||
```
|
||||
|
||||
下图展示了零钱兑换的动态规划过程,和完全背包非常相似。
|
||||
|
||||
=== "<1>"
|
||||
@@ -374,10 +374,10 @@ $$
|
||||
|
||||
零钱兑换的空间优化的处理方式和完全背包一致。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="coin_change.java"
|
||||
[class]{coin_change}-[func]{coinChangeDPComp}
|
||||
```python title="coin_change.py"
|
||||
[class]{}-[func]{coin_change_dp_comp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -386,10 +386,16 @@ $$
|
||||
[class]{}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="coin_change.py"
|
||||
[class]{}-[func]{coin_change_dp_comp}
|
||||
```java title="coin_change.java"
|
||||
[class]{coin_change}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="coin_change.cs"
|
||||
[class]{coin_change}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -398,6 +404,12 @@ $$
|
||||
[class]{}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="coin_change.swift"
|
||||
[class]{}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="coin_change.js"
|
||||
@@ -410,30 +422,6 @@ $$
|
||||
[class]{}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="coin_change.c"
|
||||
[class]{}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="coin_change.cs"
|
||||
[class]{coin_change}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="coin_change.swift"
|
||||
[class]{}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="coin_change.zig"
|
||||
[class]{}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="coin_change.dart"
|
||||
@@ -446,6 +434,18 @@ $$
|
||||
[class]{}-[func]{coin_change_dp_comp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="coin_change.c"
|
||||
[class]{}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="coin_change.zig"
|
||||
[class]{}-[func]{coinChangeDPComp}
|
||||
```
|
||||
|
||||
## 零钱兑换问题 II
|
||||
|
||||
!!! question
|
||||
@@ -468,10 +468,10 @@ $$
|
||||
|
||||
### 代码实现
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="coin_change_ii.java"
|
||||
[class]{coin_change_ii}-[func]{coinChangeIIDP}
|
||||
```python title="coin_change_ii.py"
|
||||
[class]{}-[func]{coin_change_ii_dp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -480,10 +480,16 @@ $$
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="coin_change_ii.py"
|
||||
[class]{}-[func]{coin_change_ii_dp}
|
||||
```java title="coin_change_ii.java"
|
||||
[class]{coin_change_ii}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="coin_change_ii.cs"
|
||||
[class]{coin_change_ii}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -492,6 +498,12 @@ $$
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="coin_change_ii.swift"
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="coin_change_ii.js"
|
||||
@@ -504,30 +516,6 @@ $$
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="coin_change_ii.c"
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="coin_change_ii.cs"
|
||||
[class]{coin_change_ii}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="coin_change_ii.swift"
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="coin_change_ii.zig"
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="coin_change_ii.dart"
|
||||
@@ -540,14 +528,26 @@ $$
|
||||
[class]{}-[func]{coin_change_ii_dp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="coin_change_ii.c"
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="coin_change_ii.zig"
|
||||
[class]{}-[func]{coinChangeIIDP}
|
||||
```
|
||||
|
||||
### 空间优化
|
||||
|
||||
空间优化处理方式相同,删除硬币维度即可。
|
||||
|
||||
=== "Java"
|
||||
=== "Python"
|
||||
|
||||
```java title="coin_change_ii.java"
|
||||
[class]{coin_change_ii}-[func]{coinChangeIIDPComp}
|
||||
```python title="coin_change_ii.py"
|
||||
[class]{}-[func]{coin_change_ii_dp_comp}
|
||||
```
|
||||
|
||||
=== "C++"
|
||||
@@ -556,10 +556,16 @@ $$
|
||||
[class]{}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "Python"
|
||||
=== "Java"
|
||||
|
||||
```python title="coin_change_ii.py"
|
||||
[class]{}-[func]{coin_change_ii_dp_comp}
|
||||
```java title="coin_change_ii.java"
|
||||
[class]{coin_change_ii}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="coin_change_ii.cs"
|
||||
[class]{coin_change_ii}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "Go"
|
||||
@@ -568,6 +574,12 @@ $$
|
||||
[class]{}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="coin_change_ii.swift"
|
||||
[class]{}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "JS"
|
||||
|
||||
```javascript title="coin_change_ii.js"
|
||||
@@ -580,30 +592,6 @@ $$
|
||||
[class]{}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="coin_change_ii.c"
|
||||
[class]{}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "C#"
|
||||
|
||||
```csharp title="coin_change_ii.cs"
|
||||
[class]{coin_change_ii}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "Swift"
|
||||
|
||||
```swift title="coin_change_ii.swift"
|
||||
[class]{}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="coin_change_ii.zig"
|
||||
[class]{}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "Dart"
|
||||
|
||||
```dart title="coin_change_ii.dart"
|
||||
@@ -615,3 +603,15 @@ $$
|
||||
```rust title="coin_change_ii.rs"
|
||||
[class]{}-[func]{coin_change_ii_dp_comp}
|
||||
```
|
||||
|
||||
=== "C"
|
||||
|
||||
```c title="coin_change_ii.c"
|
||||
[class]{}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
=== "Zig"
|
||||
|
||||
```zig title="coin_change_ii.zig"
|
||||
[class]{}-[func]{coinChangeIIDPComp}
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user