Fix a definition.
This commit is contained in:
parent
debf42b189
commit
9731a46d67
@ -22,7 +22,7 @@ int climbingStairsDP(int n) {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯:状态压缩后的动态规划 */
|
||||
/* 爬楼梯:空间优化后的动态规划 */
|
||||
int climbingStairsDPComp(int n) {
|
||||
if (n == 1 || n == 2)
|
||||
return n;
|
||||
|
@ -31,7 +31,7 @@ int coinChangeDP(vector<int> &coins, int amt) {
|
||||
return dp[n][amt] != MAX ? dp[n][amt] : -1;
|
||||
}
|
||||
|
||||
/* 零钱兑换:状态压缩后的动态规划 */
|
||||
/* 零钱兑换:空间优化后的动态规划 */
|
||||
int coinChangeDPComp(vector<int> &coins, int amt) {
|
||||
int n = coins.size();
|
||||
int MAX = amt + 1;
|
||||
@ -62,7 +62,7 @@ int main() {
|
||||
int res = coinChangeDP(coins, amt);
|
||||
cout << "凑到目标金额所需的最少硬币数量为 " << res << endl;
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeDPComp(coins, amt);
|
||||
cout << "凑到目标金额所需的最少硬币数量为 " << res << endl;
|
||||
|
||||
|
@ -30,7 +30,7 @@ int coinChangeIIDP(vector<int> &coins, int amt) {
|
||||
return dp[n][amt];
|
||||
}
|
||||
|
||||
/* 零钱兑换 II:状态压缩后的动态规划 */
|
||||
/* 零钱兑换 II:空间优化后的动态规划 */
|
||||
int coinChangeIIDPComp(vector<int> &coins, int amt) {
|
||||
int n = coins.size();
|
||||
// 初始化 dp 表
|
||||
@ -60,7 +60,7 @@ int main() {
|
||||
int res = coinChangeIIDP(coins, amt);
|
||||
cout << "凑出目标金额的硬币组合数量为 " << res << endl;
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeIIDPComp(coins, amt);
|
||||
cout << "凑出目标金额的硬币组合数量为 " << res << endl;
|
||||
|
||||
|
@ -80,7 +80,7 @@ int editDistanceDP(string s, string t) {
|
||||
return dp[n][m];
|
||||
}
|
||||
|
||||
/* 编辑距离:状态压缩后的动态规划 */
|
||||
/* 编辑距离:空间优化后的动态规划 */
|
||||
int editDistanceDPComp(string s, string t) {
|
||||
int n = s.length(), m = t.length();
|
||||
vector<int> dp(m + 1, 0);
|
||||
@ -128,7 +128,7 @@ int main() {
|
||||
res = editDistanceDP(s, t);
|
||||
cout << "将 " << s << " 更改为 " << t << " 最少需要编辑 " << res << " 步\n";
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = editDistanceDPComp(s, t);
|
||||
cout << "将 " << s << " 更改为 " << t << " 最少需要编辑 " << res << " 步\n";
|
||||
|
||||
|
@ -63,7 +63,7 @@ int knapsackDP(vector<int> &wgt, vector<int> &val, int cap) {
|
||||
return dp[n][cap];
|
||||
}
|
||||
|
||||
/* 0-1 背包:状态压缩后的动态规划 */
|
||||
/* 0-1 背包:空间优化后的动态规划 */
|
||||
int knapsackDPComp(vector<int> &wgt, vector<int> &val, int cap) {
|
||||
int n = wgt.size();
|
||||
// 初始化 dp 表
|
||||
@ -101,7 +101,7 @@ int main() {
|
||||
res = knapsackDP(wgt, val, cap);
|
||||
cout << "不超过背包容量的最大物品价值为 " << res << endl;
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = knapsackDPComp(wgt, val, cap);
|
||||
cout << "不超过背包容量的最大物品价值为 " << res << endl;
|
||||
|
||||
|
@ -23,7 +23,7 @@ int minCostClimbingStairsDP(vector<int> &cost) {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯最小代价:状态压缩后的动态规划 */
|
||||
/* 爬楼梯最小代价:空间优化后的动态规划 */
|
||||
int minCostClimbingStairsDPComp(vector<int> &cost) {
|
||||
int n = cost.size() - 1;
|
||||
if (n == 1 || n == 2)
|
||||
|
@ -68,7 +68,7 @@ int minPathSumDP(vector<vector<int>> &grid) {
|
||||
return dp[n - 1][m - 1];
|
||||
}
|
||||
|
||||
/* 最小路径和:状态压缩后的动态规划 */
|
||||
/* 最小路径和:空间优化后的动态规划 */
|
||||
int minPathSumDPComp(vector<vector<int>> &grid) {
|
||||
int n = grid.size(), m = grid[0].size();
|
||||
// 初始化 dp 表
|
||||
@ -108,7 +108,7 @@ int main() {
|
||||
res = minPathSumDP(grid);
|
||||
cout << "从左上角到右下角的最小路径和为 " << res << endl;
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = minPathSumDPComp(grid);
|
||||
cout << "从左上角到右下角的最小路径和为 " << res << endl;
|
||||
|
||||
|
@ -26,7 +26,7 @@ int unboundedKnapsackDP(vector<int> &wgt, vector<int> &val, int cap) {
|
||||
return dp[n][cap];
|
||||
}
|
||||
|
||||
/* 完全背包:状态压缩后的动态规划 */
|
||||
/* 完全背包:空间优化后的动态规划 */
|
||||
int unboundedKnapsackDPComp(vector<int> &wgt, vector<int> &val, int cap) {
|
||||
int n = wgt.size();
|
||||
// 初始化 dp 表
|
||||
@ -56,7 +56,7 @@ int main() {
|
||||
int res = unboundedKnapsackDP(wgt, val, cap);
|
||||
cout << "不超过背包容量的最大物品价值为 " << res << endl;
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = unboundedKnapsackDPComp(wgt, val, cap);
|
||||
cout << "不超过背包容量的最大物品价值为 " << res << endl;
|
||||
|
||||
|
@ -23,7 +23,7 @@ public class climbing_stairs_dp {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯:状态压缩后的动态规划 */
|
||||
/* 爬楼梯:空间优化后的动态规划 */
|
||||
public int climbingStairsDPComp(int n) {
|
||||
if (n == 1 || n == 2)
|
||||
return n;
|
||||
|
@ -32,7 +32,7 @@ public class coin_change {
|
||||
return dp[n, amt] != MAX ? dp[n, amt] : -1;
|
||||
}
|
||||
|
||||
/* 零钱兑换:状态压缩后的动态规划 */
|
||||
/* 零钱兑换:空间优化后的动态规划 */
|
||||
public int coinChangeDPComp(int[] coins, int amt) {
|
||||
int n = coins.Length;
|
||||
int MAX = amt + 1;
|
||||
@ -64,7 +64,7 @@ public class coin_change {
|
||||
int res = coinChangeDP(coins, amt);
|
||||
Console.WriteLine("凑到目标金额所需的最少硬币数量为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeDPComp(coins, amt);
|
||||
Console.WriteLine("凑到目标金额所需的最少硬币数量为 " + res);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class coin_change_ii {
|
||||
return dp[n, amt];
|
||||
}
|
||||
|
||||
/* 零钱兑换 II:状态压缩后的动态规划 */
|
||||
/* 零钱兑换 II:空间优化后的动态规划 */
|
||||
public int coinChangeIIDPComp(int[] coins, int amt) {
|
||||
int n = coins.Length;
|
||||
// 初始化 dp 表
|
||||
@ -61,7 +61,7 @@ public class coin_change_ii {
|
||||
int res = coinChangeIIDP(coins, amt);
|
||||
Console.WriteLine("凑出目标金额的硬币组合数量为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeIIDPComp(coins, amt);
|
||||
Console.WriteLine("凑出目标金额的硬币组合数量为 " + res);
|
||||
}
|
||||
|
@ -81,7 +81,7 @@ public class edit_distance {
|
||||
return dp[n, m];
|
||||
}
|
||||
|
||||
/* 编辑距离:状态压缩后的动态规划 */
|
||||
/* 编辑距离:空间优化后的动态规划 */
|
||||
public int editDistanceDPComp(string s, string t) {
|
||||
int n = s.Length, m = t.Length;
|
||||
int[] dp = new int[m + 1];
|
||||
@ -134,7 +134,7 @@ public class edit_distance {
|
||||
res = editDistanceDP(s, t);
|
||||
Console.WriteLine("将 " + s + " 更改为 " + t + " 最少需要编辑 " + res + " 步");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = editDistanceDPComp(s, t);
|
||||
Console.WriteLine("将 " + s + " 更改为 " + t + " 最少需要编辑 " + res + " 步");
|
||||
}
|
||||
|
@ -66,7 +66,7 @@ public class knapsack {
|
||||
return dp[n, cap];
|
||||
}
|
||||
|
||||
/* 0-1 背包:状态压缩后的动态规划 */
|
||||
/* 0-1 背包:空间优化后的动态规划 */
|
||||
public int knapsackDPComp(int[] weight, int[] val, int cap) {
|
||||
int n = weight.Length;
|
||||
// 初始化 dp 表
|
||||
@ -111,7 +111,7 @@ public class knapsack {
|
||||
res = knapsackDP(weight, val, cap);
|
||||
Console.WriteLine("不超过背包容量的最大物品价值为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = knapsackDPComp(weight, val, cap);
|
||||
Console.WriteLine("不超过背包容量的最大物品价值为 " + res);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public class min_cost_climbing_stairs_dp {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯最小代价:状态压缩后的动态规划 */
|
||||
/* 爬楼梯最小代价:空间优化后的动态规划 */
|
||||
public int minCostClimbingStairsDPComp(int[] cost) {
|
||||
int n = cost.Length - 1;
|
||||
if (n == 1 || n == 2)
|
||||
|
@ -69,7 +69,7 @@ public class min_path_sum {
|
||||
return dp[n - 1, m - 1];
|
||||
}
|
||||
|
||||
/* 最小路径和:状态压缩后的动态规划 */
|
||||
/* 最小路径和:空间优化后的动态规划 */
|
||||
public int minPathSumDPComp(int[][] grid) {
|
||||
int n = grid.Length, m = grid[0].Length;
|
||||
// 初始化 dp 表
|
||||
@ -120,7 +120,7 @@ public class min_path_sum {
|
||||
res = minPathSumDP(grid);
|
||||
Console.WriteLine("从左上角到右下角的做小路径和为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = minPathSumDPComp(grid);
|
||||
Console.WriteLine("从左上角到右下角的做小路径和为 " + res);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class unbounded_knapsack {
|
||||
return dp[n, cap];
|
||||
}
|
||||
|
||||
/* 完全背包:状态压缩后的动态规划 */
|
||||
/* 完全背包:空间优化后的动态规划 */
|
||||
public int unboundedKnapsackDPComp(int[] wgt, int[] val, int cap) {
|
||||
int n = wgt.Length;
|
||||
// 初始化 dp 表
|
||||
@ -57,7 +57,7 @@ public class unbounded_knapsack {
|
||||
int res = unboundedKnapsackDP(wgt, val, cap);
|
||||
Console.WriteLine("不超过背包容量的最大物品价值为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = unboundedKnapsackDPComp(wgt, val, cap);
|
||||
Console.WriteLine("不超过背包容量的最大物品价值为 " + res);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ int climbingStairsDP(int n) {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯:状态压缩后的动态规划 */
|
||||
/* 爬楼梯:空间优化后的动态规划 */
|
||||
int climbingStairsDPComp(int n) {
|
||||
if (n == 1 || n == 2) return n;
|
||||
int a = 1, b = 2;
|
||||
|
@ -31,7 +31,7 @@ int coinChangeDP(List<int> coins, int amt) {
|
||||
return dp[n][amt] != MAX ? dp[n][amt] : -1;
|
||||
}
|
||||
|
||||
/* 零钱兑换:状态压缩后的动态规划 */
|
||||
/* 零钱兑换:空间优化后的动态规划 */
|
||||
int coinChangeDPComp(List<int> coins, int amt) {
|
||||
int n = coins.length;
|
||||
int MAX = amt + 1;
|
||||
@ -62,7 +62,7 @@ void main() {
|
||||
int res = coinChangeDP(coins, amt);
|
||||
print("凑到目标金额所需的最少硬币数量为 $res");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeDPComp(coins, amt);
|
||||
print("凑到目标金额所需的最少硬币数量为 $res");
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ int coinChangeIIDP(List<int> coins, int amt) {
|
||||
return dp[n][amt];
|
||||
}
|
||||
|
||||
/* 零钱兑换 II:状态压缩后的动态规划 */
|
||||
/* 零钱兑换 II:空间优化后的动态规划 */
|
||||
int coinChangeIIDPComp(List<int> coins, int amt) {
|
||||
int n = coins.length;
|
||||
// 初始化 dp 表
|
||||
@ -58,7 +58,7 @@ void main() {
|
||||
int res = coinChangeIIDP(coins, amt);
|
||||
print("凑出目标金额的硬币组合数量为 $res");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeIIDPComp(coins, amt);
|
||||
print("凑出目标金额的硬币组合数量为 $res");
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ int editDistanceDP(String s, String t) {
|
||||
return dp[n][m];
|
||||
}
|
||||
|
||||
/* 编辑距离:状态压缩后的动态规划 */
|
||||
/* 编辑距离:空间优化后的动态规划 */
|
||||
int editDistanceDPComp(String s, String t) {
|
||||
int n = s.length, m = t.length;
|
||||
List<int> dp = List.filled(m + 1, 0);
|
||||
@ -119,7 +119,7 @@ void main() {
|
||||
res = editDistanceDP(s, t);
|
||||
print("将 " + s + " 更改为 " + t + " 最少需要编辑 $res 步");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = editDistanceDPComp(s, t);
|
||||
print("将 " + s + " 更改为 " + t + " 最少需要编辑 $res 步");
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ int knapsackDP(List<int> wgt, List<int> val, int cap) {
|
||||
return dp[n][cap];
|
||||
}
|
||||
|
||||
/* 0-1 背包:状态压缩后的动态规划 */
|
||||
/* 0-1 背包:空间优化后的动态规划 */
|
||||
int knapsackDPComp(List<int> wgt, List<int> val, int cap) {
|
||||
int n = wgt.length;
|
||||
// 初始化 dp 表
|
||||
@ -110,7 +110,7 @@ void main() {
|
||||
res = knapsackDP(wgt, val, cap);
|
||||
print("不超过背包容量的最大物品价值为 $res");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = knapsackDPComp(wgt, val, cap);
|
||||
print("不超过背包容量的最大物品价值为 $res");
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ int minCostClimbingStairsDP(List<int> cost) {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯最小代价:状态压缩后的动态规划 */
|
||||
/* 爬楼梯最小代价:空间优化后的动态规划 */
|
||||
int minCostClimbingStairsDPComp(List<int> cost) {
|
||||
int n = cost.length - 1;
|
||||
if (n == 1 || n == 2) return cost[n];
|
||||
|
@ -70,7 +70,7 @@ int minPathSumDP(List<List<int>> grid) {
|
||||
return dp[n - 1][m - 1];
|
||||
}
|
||||
|
||||
/* 最小路径和:状态压缩后的动态规划 */
|
||||
/* 最小路径和:空间优化后的动态规划 */
|
||||
int minPathSumDPComp(List<List<int>> grid) {
|
||||
int n = grid.length, m = grid[0].length;
|
||||
// 初始化 dp 表
|
||||
@ -114,7 +114,7 @@ void main() {
|
||||
res = minPathSumDP(grid);
|
||||
print("从左上角到右下角的做小路径和为 $res");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = minPathSumDPComp(grid);
|
||||
print("从左上角到右下角的做小路径和为 $res");
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ int unboundedKnapsackDP(List<int> wgt, List<int> val, int cap) {
|
||||
return dp[n][cap];
|
||||
}
|
||||
|
||||
/* 完全背包:状态压缩后的动态规划 */
|
||||
/* 完全背包:空间优化后的动态规划 */
|
||||
int unboundedKnapsackDPComp(List<int> wgt, List<int> val, int cap) {
|
||||
int n = wgt.length;
|
||||
// 初始化 dp 表
|
||||
@ -56,7 +56,7 @@ void main() {
|
||||
int res = unboundedKnapsackDP(wgt, val, cap);
|
||||
print("不超过背包容量的最大物品价值为 $res");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
int resComp = unboundedKnapsackDPComp(wgt, val, cap);
|
||||
print("不超过背包容量的最大物品价值为 $resComp");
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ func climbingStairsDP(n int) int {
|
||||
return dp[n]
|
||||
}
|
||||
|
||||
/* 爬楼梯:状态压缩后的动态规划 */
|
||||
/* 爬楼梯:空间优化后的动态规划 */
|
||||
func climbingStairsDPComp(n int) int {
|
||||
if n == 1 || n == 2 {
|
||||
return n
|
||||
|
@ -31,7 +31,7 @@ func coinChangeIIDP(coins []int, amt int) int {
|
||||
return dp[n][amt]
|
||||
}
|
||||
|
||||
/* 零钱兑换 II:状态压缩后的动态规划 */
|
||||
/* 零钱兑换 II:空间优化后的动态规划 */
|
||||
func coinChangeIIDPComp(coins []int, amt int) int {
|
||||
n := len(coins)
|
||||
// 初始化 dp 表
|
||||
|
@ -17,7 +17,7 @@ func TestCoinChange(t *testing.T) {
|
||||
res := coinChangeDP(coins, amt)
|
||||
fmt.Printf("凑到目标金额所需的最少硬币数量为 %d\n", res)
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeDPComp(coins, amt)
|
||||
fmt.Printf("凑到目标金额所需的最少硬币数量为 %d\n", res)
|
||||
}
|
||||
|
@ -91,7 +91,7 @@ func editDistanceDP(s string, t string) int {
|
||||
return dp[n][m]
|
||||
}
|
||||
|
||||
/* 编辑距离:状态压缩后的动态规划 */
|
||||
/* 编辑距离:空间优化后的动态规划 */
|
||||
func editDistanceDPComp(s string, t string) int {
|
||||
n := len(s)
|
||||
m := len(t)
|
||||
|
@ -34,7 +34,7 @@ func TestEditDistanceDFS(test *testing.T) {
|
||||
res = editDistanceDP(s, t)
|
||||
fmt.Printf("将 %s 更改为 %s 最少需要编辑 %d 步\n", s, t, res)
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = editDistanceDPComp(s, t)
|
||||
fmt.Printf("将 %s 更改为 %s 最少需要编辑 %d 步\n", s, t, res)
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ func knapsackDP(wgt, val []int, cap int) int {
|
||||
return dp[n][cap]
|
||||
}
|
||||
|
||||
/* 0-1 背包:状态压缩后的动态规划 */
|
||||
/* 0-1 背包:空间优化后的动态规划 */
|
||||
func knapsackDPComp(wgt, val []int, cap int) int {
|
||||
n := len(wgt)
|
||||
// 初始化 dp 表
|
||||
|
@ -34,7 +34,7 @@ func TestKnapsack(t *testing.T) {
|
||||
res = knapsackDP(wgt, val, c)
|
||||
fmt.Printf("不超过背包容量的最大物品价值为 %d\n", res)
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = knapsackDPComp(wgt, val, c)
|
||||
fmt.Printf("不超过背包容量的最大物品价值为 %d\n", res)
|
||||
}
|
||||
@ -48,7 +48,7 @@ func TestUnboundedKnapsack(t *testing.T) {
|
||||
res := unboundedKnapsackDP(wgt, val, c)
|
||||
fmt.Printf("不超过背包容量的最大物品价值为 %d\n", res)
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = unboundedKnapsackDPComp(wgt, val, c)
|
||||
fmt.Printf("不超过背包容量的最大物品价值为 %d\n", res)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ func minCostClimbingStairsDP(cost []int) int {
|
||||
return dp[n]
|
||||
}
|
||||
|
||||
/* 爬楼梯最小代价:状态压缩后的动态规划 */
|
||||
/* 爬楼梯最小代价:空间优化后的动态规划 */
|
||||
func minCostClimbingStairsDPComp(cost []int) int {
|
||||
n := len(cost) - 1
|
||||
if n == 1 || n == 2 {
|
||||
|
@ -71,7 +71,7 @@ func minPathSumDP(grid [][]int) int {
|
||||
return dp[n-1][m-1]
|
||||
}
|
||||
|
||||
/* 最小路径和:状态压缩后的动态规划 */
|
||||
/* 最小路径和:空间优化后的动态规划 */
|
||||
func minPathSumDPComp(grid [][]int) int {
|
||||
n, m := len(grid), len(grid[0])
|
||||
// 初始化 dp 表
|
||||
|
@ -37,7 +37,7 @@ func TestMinPathSum(t *testing.T) {
|
||||
res = minPathSumDP(grid)
|
||||
fmt.Printf("从左上角到右下角的做小路径和为 %d\n", res)
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = minPathSumDPComp(grid)
|
||||
fmt.Printf("从左上角到右下角的做小路径和为 %d\n", res)
|
||||
}
|
||||
|
@ -29,7 +29,7 @@ func unboundedKnapsackDP(wgt, val []int, cap int) int {
|
||||
return dp[n][cap]
|
||||
}
|
||||
|
||||
/* 完全背包:状态压缩后的动态规划 */
|
||||
/* 完全背包:空间优化后的动态规划 */
|
||||
func unboundedKnapsackDPComp(wgt, val []int, cap int) int {
|
||||
n := len(wgt)
|
||||
// 初始化 dp 表
|
||||
|
@ -23,7 +23,7 @@ public class climbing_stairs_dp {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯:状态压缩后的动态规划 */
|
||||
/* 爬楼梯:空间优化后的动态规划 */
|
||||
public static int climbingStairsDPComp(int n) {
|
||||
if (n == 1 || n == 2)
|
||||
return n;
|
||||
|
@ -34,7 +34,7 @@ public class coin_change {
|
||||
return dp[n][amt] != MAX ? dp[n][amt] : -1;
|
||||
}
|
||||
|
||||
/* 零钱兑换:状态压缩后的动态规划 */
|
||||
/* 零钱兑换:空间优化后的动态规划 */
|
||||
static int coinChangeDPComp(int[] coins, int amt) {
|
||||
int n = coins.length;
|
||||
int MAX = amt + 1;
|
||||
@ -65,7 +65,7 @@ public class coin_change {
|
||||
int res = coinChangeDP(coins, amt);
|
||||
System.out.println("凑到目标金额所需的最少硬币数量为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeDPComp(coins, amt);
|
||||
System.out.println("凑到目标金额所需的最少硬币数量为 " + res);
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ public class coin_change_ii {
|
||||
return dp[n][amt];
|
||||
}
|
||||
|
||||
/* 零钱兑换 II:状态压缩后的动态规划 */
|
||||
/* 零钱兑换 II:空间优化后的动态规划 */
|
||||
static int coinChangeIIDPComp(int[] coins, int amt) {
|
||||
int n = coins.length;
|
||||
// 初始化 dp 表
|
||||
@ -60,7 +60,7 @@ public class coin_change_ii {
|
||||
int res = coinChangeIIDP(coins, amt);
|
||||
System.out.println("凑出目标金额的硬币组合数量为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeIIDPComp(coins, amt);
|
||||
System.out.println("凑出目标金额的硬币组合数量为 " + res);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ public class edit_distance {
|
||||
return dp[n][m];
|
||||
}
|
||||
|
||||
/* 编辑距离:状态压缩后的动态规划 */
|
||||
/* 编辑距离:空间优化后的动态规划 */
|
||||
static int editDistanceDPComp(String s, String t) {
|
||||
int n = s.length(), m = t.length();
|
||||
int[] dp = new int[m + 1];
|
||||
@ -132,7 +132,7 @@ public class edit_distance {
|
||||
res = editDistanceDP(s, t);
|
||||
System.out.println("将 " + s + " 更改为 " + t + " 最少需要编辑 " + res + " 步");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = editDistanceDPComp(s, t);
|
||||
System.out.println("将 " + s + " 更改为 " + t + " 最少需要编辑 " + res + " 步");
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ public class knapsack {
|
||||
return dp[n][cap];
|
||||
}
|
||||
|
||||
/* 0-1 背包:状态压缩后的动态规划 */
|
||||
/* 0-1 背包:空间优化后的动态规划 */
|
||||
static int knapsackDPComp(int[] wgt, int[] val, int cap) {
|
||||
int n = wgt.length;
|
||||
// 初始化 dp 表
|
||||
@ -109,7 +109,7 @@ public class knapsack {
|
||||
res = knapsackDP(wgt, val, cap);
|
||||
System.out.println("不超过背包容量的最大物品价值为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = knapsackDPComp(wgt, val, cap);
|
||||
System.out.println("不超过背包容量的最大物品价值为 " + res);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public class min_cost_climbing_stairs_dp {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯最小代价:状态压缩后的动态规划 */
|
||||
/* 爬楼梯最小代价:空间优化后的动态规划 */
|
||||
public static int minCostClimbingStairsDPComp(int[] cost) {
|
||||
int n = cost.length - 1;
|
||||
if (n == 1 || n == 2)
|
||||
|
@ -71,7 +71,7 @@ public class min_path_sum {
|
||||
return dp[n - 1][m - 1];
|
||||
}
|
||||
|
||||
/* 最小路径和:状态压缩后的动态规划 */
|
||||
/* 最小路径和:空间优化后的动态规划 */
|
||||
static int minPathSumDPComp(int[][] grid) {
|
||||
int n = grid.length, m = grid[0].length;
|
||||
// 初始化 dp 表
|
||||
@ -118,7 +118,7 @@ public class min_path_sum {
|
||||
res = minPathSumDP(grid);
|
||||
System.out.println("从左上角到右下角的做小路径和为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = minPathSumDPComp(grid);
|
||||
System.out.println("从左上角到右下角的做小路径和为 " + res);
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ public class unbounded_knapsack {
|
||||
return dp[n][cap];
|
||||
}
|
||||
|
||||
/* 完全背包:状态压缩后的动态规划 */
|
||||
/* 完全背包:空间优化后的动态规划 */
|
||||
static int unboundedKnapsackDPComp(int[] wgt, int[] val, int cap) {
|
||||
int n = wgt.length;
|
||||
// 初始化 dp 表
|
||||
@ -56,7 +56,7 @@ public class unbounded_knapsack {
|
||||
int res = unboundedKnapsackDP(wgt, val, cap);
|
||||
System.out.println("不超过背包容量的最大物品价值为 " + res);
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = unboundedKnapsackDPComp(wgt, val, cap);
|
||||
System.out.println("不超过背包容量的最大物品价值为 " + res);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ function climbingStairsDP(n) {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯:状态压缩后的动态规划 */
|
||||
/* 爬楼梯:空间优化后的动态规划 */
|
||||
function climbingStairsDPComp(n) {
|
||||
if (n === 1 || n === 2) return n;
|
||||
let a = 1,
|
||||
|
@ -20,7 +20,7 @@ def climbing_stairs_dp(n: int) -> int:
|
||||
|
||||
|
||||
def climbing_stairs_dp_comp(n: int) -> int:
|
||||
"""爬楼梯:状态压缩后的动态规划"""
|
||||
"""爬楼梯:空间优化后的动态规划"""
|
||||
if n == 1 or n == 2:
|
||||
return n
|
||||
a, b = 1, 2
|
||||
|
@ -27,7 +27,7 @@ def coin_change_dp(coins: list[int], amt: int) -> int:
|
||||
|
||||
|
||||
def coin_change_dp_comp(coins: list[int], amt: int) -> int:
|
||||
"""零钱兑换:状态压缩后的动态规划"""
|
||||
"""零钱兑换:空间优化后的动态规划"""
|
||||
n = len(coins)
|
||||
MAX = amt + 1
|
||||
# 初始化 dp 表
|
||||
@ -55,6 +55,6 @@ if __name__ == "__main__":
|
||||
res = coin_change_dp(coins, amt)
|
||||
print(f"凑到目标金额所需的最少硬币数量为 {res}")
|
||||
|
||||
# 状态压缩后的动态规划
|
||||
# 空间优化后的动态规划
|
||||
res = coin_change_dp_comp(coins, amt)
|
||||
print(f"凑到目标金额所需的最少硬币数量为 {res}")
|
||||
|
@ -26,7 +26,7 @@ def coin_change_ii_dp(coins: list[int], amt: int) -> int:
|
||||
|
||||
|
||||
def coin_change_ii_dp_comp(coins: list[int], amt: int) -> int:
|
||||
"""零钱兑换 II:状态压缩后的动态规划"""
|
||||
"""零钱兑换 II:空间优化后的动态规划"""
|
||||
n = len(coins)
|
||||
# 初始化 dp 表
|
||||
dp = [0] * (amt + 1)
|
||||
@ -54,6 +54,6 @@ if __name__ == "__main__":
|
||||
res = coin_change_ii_dp(coins, amt)
|
||||
print(f"凑出目标金额的硬币组合数量为 {res}")
|
||||
|
||||
# 状态压缩后的动态规划
|
||||
# 空间优化后的动态规划
|
||||
res = coin_change_ii_dp_comp(coins, amt)
|
||||
print(f"凑出目标金额的硬币组合数量为 {res}")
|
||||
|
@ -75,7 +75,7 @@ def edit_distance_dp(s: str, t: str) -> int:
|
||||
|
||||
|
||||
def edit_distance_dp_comp(s: str, t: str) -> int:
|
||||
"""编辑距离:状态压缩后的动态规划"""
|
||||
"""编辑距离:空间优化后的动态规划"""
|
||||
n, m = len(s), len(t)
|
||||
dp = [0] * (m + 1)
|
||||
# 状态转移:首行
|
||||
@ -118,6 +118,6 @@ if __name__ == "__main__":
|
||||
res = edit_distance_dp(s, t)
|
||||
print(f"将 {s} 更改为 {t} 最少需要编辑 {res} 步")
|
||||
|
||||
# 状态压缩后的动态规划
|
||||
# 空间优化后的动态规划
|
||||
res = edit_distance_dp_comp(s, t)
|
||||
print(f"将 {s} 更改为 {t} 最少需要编辑 {res} 步")
|
||||
|
@ -59,7 +59,7 @@ def knapsack_dp(wgt: list[int], val: list[int], cap: int) -> int:
|
||||
|
||||
|
||||
def knapsack_dp_comp(wgt: list[int], val: list[int], cap: int) -> int:
|
||||
"""0-1 背包:状态压缩后的动态规划"""
|
||||
"""0-1 背包:空间优化后的动态规划"""
|
||||
n = len(wgt)
|
||||
# 初始化 dp 表
|
||||
dp = [0] * (cap + 1)
|
||||
@ -96,6 +96,6 @@ if __name__ == "__main__":
|
||||
res = knapsack_dp(wgt, val, cap)
|
||||
print(f"不超过背包容量的最大物品价值为 {res}")
|
||||
|
||||
# 状态压缩后的动态规划
|
||||
# 空间优化后的动态规划
|
||||
res = knapsack_dp_comp(wgt, val, cap)
|
||||
print(f"不超过背包容量的最大物品价值为 {res}")
|
||||
|
@ -21,7 +21,7 @@ def min_cost_climbing_stairs_dp(cost: list[int]) -> int:
|
||||
|
||||
|
||||
def min_cost_climbing_stairs_dp_comp(cost: list[int]) -> int:
|
||||
"""爬楼梯最小代价:状态压缩后的动态规划"""
|
||||
"""爬楼梯最小代价:空间优化后的动态规划"""
|
||||
n = len(cost) - 1
|
||||
if n == 1 or n == 2:
|
||||
return cost[n]
|
||||
|
@ -63,7 +63,7 @@ def min_path_sum_dp(grid: list[list[int]]) -> int:
|
||||
|
||||
|
||||
def min_path_sum_dp_comp(grid: list[list[int]]) -> int:
|
||||
"""最小路径和:状态压缩后的动态规划"""
|
||||
"""最小路径和:空间优化后的动态规划"""
|
||||
n, m = len(grid), len(grid[0])
|
||||
# 初始化 dp 表
|
||||
dp = [0] * m
|
||||
@ -99,6 +99,6 @@ if __name__ == "__main__":
|
||||
res = min_path_sum_dp(grid)
|
||||
print(f"从左上角到右下角的做小路径和为 {res}")
|
||||
|
||||
# 状态压缩后的动态规划
|
||||
# 空间优化后的动态规划
|
||||
res = min_path_sum_dp_comp(grid)
|
||||
print(f"从左上角到右下角的做小路径和为 {res}")
|
||||
|
@ -23,7 +23,7 @@ def unbounded_knapsack_dp(wgt: list[int], val: list[int], cap: int) -> int:
|
||||
|
||||
|
||||
def unbounded_knapsack_dp_comp(wgt: list[int], val: list[int], cap: int) -> int:
|
||||
"""完全背包:状态压缩后的动态规划"""
|
||||
"""完全背包:空间优化后的动态规划"""
|
||||
n = len(wgt)
|
||||
# 初始化 dp 表
|
||||
dp = [0] * (cap + 1)
|
||||
@ -50,6 +50,6 @@ if __name__ == "__main__":
|
||||
res = unbounded_knapsack_dp(wgt, val, cap)
|
||||
print(f"不超过背包容量的最大物品价值为 {res}")
|
||||
|
||||
# 状态压缩后的动态规划
|
||||
# 空间优化后的动态规划
|
||||
res = unbounded_knapsack_dp_comp(wgt, val, cap)
|
||||
print(f"不超过背包容量的最大物品价值为 {res}")
|
||||
|
@ -20,7 +20,7 @@ fn climbing_stairs_dp(n: usize) -> i32 {
|
||||
dp[n]
|
||||
}
|
||||
|
||||
/* 爬楼梯:状态压缩后的动态规划 */
|
||||
/* 爬楼梯:空间优化后的动态规划 */
|
||||
fn climbing_stairs_dp_comp(n: usize) -> i32 {
|
||||
if n == 1 || n == 2 { return n as i32; }
|
||||
let (mut a, mut b) = (1, 2);
|
||||
|
@ -29,7 +29,7 @@ fn coin_change_dp(coins: &[i32], amt: usize) -> i32 {
|
||||
if dp[n][amt] != max { return dp[n][amt] as i32; } else { -1 }
|
||||
}
|
||||
|
||||
/* 零钱兑换:状态压缩后的动态规划 */
|
||||
/* 零钱兑换:空间优化后的动态规划 */
|
||||
fn coin_change_dp_comp(coins: &[i32], amt: usize) -> i32 {
|
||||
let n = coins.len();
|
||||
let max = amt + 1;
|
||||
@ -61,7 +61,7 @@ pub fn main() {
|
||||
let res = coin_change_dp(&coins, amt);
|
||||
println!("凑到目标金额所需的最少硬币数量为 {res}");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
let res = coin_change_dp_comp(&coins, amt);
|
||||
println!("凑到目标金额所需的最少硬币数量为 {res}");
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ fn coin_change_ii_dp(coins: &[i32], amt: usize) -> i32 {
|
||||
dp[n][amt]
|
||||
}
|
||||
|
||||
/* 零钱兑换 II:状态压缩后的动态规划 */
|
||||
/* 零钱兑换 II:空间优化后的动态规划 */
|
||||
fn coin_change_ii_dp_comp(coins: &[i32], amt: usize) -> i32 {
|
||||
let n = coins.len();
|
||||
// 初始化 dp 表
|
||||
@ -58,7 +58,7 @@ pub fn main() {
|
||||
let res = coin_change_ii_dp(&coins, amt);
|
||||
println!("凑出目标金额的硬币组合数量为 {res}");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
let res = coin_change_dp_ii_comp(&coins, amt);
|
||||
println!("凑出目标金额的硬币组合数量为 {res}");
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ fn edit_distance_dp(s: &str, t: &str) -> i32 {
|
||||
dp[n][m]
|
||||
}
|
||||
|
||||
/* 编辑距离:状态压缩后的动态规划 */
|
||||
/* 编辑距离:空间优化后的动态规划 */
|
||||
fn edit_distance_dp_comp(s: &str, t: &str) -> i32 {
|
||||
let (n, m) = (s.len(), t.len());
|
||||
let mut dp = vec![0; m + 1];
|
||||
@ -124,7 +124,7 @@ pub fn main() {
|
||||
let res = edit_distance_dp(s, t);
|
||||
println!("将 {s} 更改为 {t} 最少需要编辑 {res} 步");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
let res = edit_distance_dp_comp(s, t);
|
||||
println!("将 {s} 更改为 {t} 最少需要编辑 {res} 步");
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ fn knapsack_dp(wgt: &[i32], val: &[i32], cap: usize) -> i32 {
|
||||
dp[n][cap]
|
||||
}
|
||||
|
||||
/* 0-1 背包:状态压缩后的动态规划 */
|
||||
/* 0-1 背包:空间优化后的动态规划 */
|
||||
fn knapsack_dp_comp(wgt: &[i32], val: &[i32], cap: usize) -> i32 {
|
||||
let n = wgt.len();
|
||||
// 初始化 dp 表
|
||||
@ -104,7 +104,7 @@ pub fn main() {
|
||||
let res = knapsack_dp(&wgt, &val, cap);
|
||||
println!("不超过背包容量的最大物品价值为 {res}");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
let res = knapsack_dp_comp(&wgt, &val, cap);
|
||||
println!("不超过背包容量的最大物品价值为 {res}");
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ fn min_cost_climbing_stairs_dp(cost: &[i32]) -> i32 {
|
||||
dp[n]
|
||||
}
|
||||
|
||||
/* 爬楼梯最小代价:状态压缩后的动态规划 */
|
||||
/* 爬楼梯最小代价:空间优化后的动态规划 */
|
||||
fn min_cost_climbing_stairs_dp_comp(cost: &[i32]) -> i32 {
|
||||
let n = cost.len() - 1;
|
||||
if n == 1 || n == 2 { return cost[n] };
|
||||
|
@ -66,7 +66,7 @@ fn min_path_sum_dp(grid: &Vec<Vec<i32>>) -> i32 {
|
||||
dp[n - 1][m - 1]
|
||||
}
|
||||
|
||||
/* 最小路径和:状态压缩后的动态规划 */
|
||||
/* 最小路径和:空间优化后的动态规划 */
|
||||
fn min_path_sum_dp_comp(grid: &Vec<Vec<i32>>) -> i32 {
|
||||
let (n, m) = (grid.len(), grid[0].len());
|
||||
// 初始化 dp 表
|
||||
@ -113,7 +113,7 @@ pub fn main() {
|
||||
let res = min_path_sum_dp(&grid);
|
||||
println!("从左上角到右下角的最小路径和为 {res}");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
let res = min_path_sum_dp_comp(&grid);
|
||||
println!("从左上角到右下角的最小路径和为 {res}");
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ fn unbounded_knapsack_dp(wgt: &[i32], val: &[i32], cap: usize) -> i32 {
|
||||
return dp[n][cap];
|
||||
}
|
||||
|
||||
/* 完全背包:状态压缩后的动态规划 */
|
||||
/* 完全背包:空间优化后的动态规划 */
|
||||
fn unbounded_knapsack_dp_comp(wgt: &[i32], val: &[i32], cap: usize) -> i32 {
|
||||
let n = wgt.len();
|
||||
// 初始化 dp 表
|
||||
@ -54,7 +54,7 @@ pub fn main() {
|
||||
let res = unbounded_knapsack_dp(&wgt, &val, cap);
|
||||
println!("不超过背包容量的最大物品价值为 {res}");
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
let res = unbounded_knapsack_dp_comp(&wgt, &val, cap);
|
||||
println!("不超过背包容量的最大物品价值为 {res}");
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ func climbingStairsDP(n: Int) -> Int {
|
||||
return dp[n]
|
||||
}
|
||||
|
||||
/* 爬楼梯:状态压缩后的动态规划 */
|
||||
/* 爬楼梯:空间优化后的动态规划 */
|
||||
func climbingStairsDPComp(n: Int) -> Int {
|
||||
if n == 1 || n == 2 {
|
||||
return n
|
||||
|
@ -29,7 +29,7 @@ func coinChangeDP(coins: [Int], amt: Int) -> Int {
|
||||
return dp[n][amt] != MAX ? dp[n][amt] : -1
|
||||
}
|
||||
|
||||
/* 零钱兑换:状态压缩后的动态规划 */
|
||||
/* 零钱兑换:空间优化后的动态规划 */
|
||||
func coinChangeDPComp(coins: [Int], amt: Int) -> Int {
|
||||
let n = coins.count
|
||||
let MAX = amt + 1
|
||||
@ -62,7 +62,7 @@ enum CoinChange {
|
||||
var res = coinChangeDP(coins: coins, amt: amt)
|
||||
print("凑到目标金额所需的最少硬币数量为 \(res)")
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeDPComp(coins: coins, amt: amt)
|
||||
print("凑到目标金额所需的最少硬币数量为 \(res)")
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ func coinChangeIIDP(coins: [Int], amt: Int) -> Int {
|
||||
return dp[n][amt]
|
||||
}
|
||||
|
||||
/* 零钱兑换 II:状态压缩后的动态规划 */
|
||||
/* 零钱兑换 II:空间优化后的动态规划 */
|
||||
func coinChangeIIDPComp(coins: [Int], amt: Int) -> Int {
|
||||
let n = coins.count
|
||||
// 初始化 dp 表
|
||||
@ -60,7 +60,7 @@ enum CoinChangeII {
|
||||
var res = coinChangeIIDP(coins: coins, amt: amt)
|
||||
print("凑出目标金额的硬币组合数量为 \(res)")
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeIIDPComp(coins: coins, amt: amt)
|
||||
print("凑出目标金额的硬币组合数量为 \(res)")
|
||||
}
|
||||
|
@ -88,7 +88,7 @@ func editDistanceDP(s: String, t: String) -> Int {
|
||||
return dp[n][m]
|
||||
}
|
||||
|
||||
/* 编辑距离:状态压缩后的动态规划 */
|
||||
/* 编辑距离:空间优化后的动态规划 */
|
||||
func editDistanceDPComp(s: String, t: String) -> Int {
|
||||
let n = s.utf8CString.count
|
||||
let m = t.utf8CString.count
|
||||
@ -140,7 +140,7 @@ enum EditDistance {
|
||||
res = editDistanceDP(s: s, t: t)
|
||||
print("将 \(s) 更改为 \(t) 最少需要编辑 \(res) 步")
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = editDistanceDPComp(s: s, t: t)
|
||||
print("将 \(s) 更改为 \(t) 最少需要编辑 \(res) 步")
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ func knapsackDP(wgt: [Int], val: [Int], cap: Int) -> Int {
|
||||
return dp[n][cap]
|
||||
}
|
||||
|
||||
/* 0-1 背包:状态压缩后的动态规划 */
|
||||
/* 0-1 背包:空间优化后的动态规划 */
|
||||
func knapsackDPComp(wgt: [Int], val: [Int], cap: Int) -> Int {
|
||||
let n = wgt.count
|
||||
// 初始化 dp 表
|
||||
@ -103,7 +103,7 @@ enum Knapsack {
|
||||
res = knapsackDP(wgt: wgt, val: val, cap: cap)
|
||||
print("不超过背包容量的最大物品价值为 \(res)")
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = knapsackDPComp(wgt: wgt, val: val, cap: cap)
|
||||
print("不超过背包容量的最大物品价值为 \(res)")
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ func minCostClimbingStairsDP(cost: [Int]) -> Int {
|
||||
return dp[n]
|
||||
}
|
||||
|
||||
/* 爬楼梯最小代价:状态压缩后的动态规划 */
|
||||
/* 爬楼梯最小代价:空间优化后的动态规划 */
|
||||
func minCostClimbingStairsDPComp(cost: [Int]) -> Int {
|
||||
let n = cost.count - 1
|
||||
if n == 1 || n == 2 {
|
||||
|
@ -67,7 +67,7 @@ func minPathSumDP(grid: [[Int]]) -> Int {
|
||||
return dp[n - 1][m - 1]
|
||||
}
|
||||
|
||||
/* 最小路径和:状态压缩后的动态规划 */
|
||||
/* 最小路径和:空间优化后的动态规划 */
|
||||
func minPathSumDPComp(grid: [[Int]]) -> Int {
|
||||
let n = grid.count
|
||||
let m = grid[0].count
|
||||
@ -116,7 +116,7 @@ enum MinPathSum {
|
||||
res = minPathSumDP(grid: grid)
|
||||
print("从左上角到右下角的做小路径和为 \(res)")
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = minPathSumDPComp(grid: grid)
|
||||
print("从左上角到右下角的做小路径和为 \(res)")
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ func unboundedKnapsackDP(wgt: [Int], val: [Int], cap: Int) -> Int {
|
||||
return dp[n][cap]
|
||||
}
|
||||
|
||||
/* 完全背包:状态压缩后的动态规划 */
|
||||
/* 完全背包:空间优化后的动态规划 */
|
||||
func unboundedKnapsackDPComp(wgt: [Int], val: [Int], cap: Int) -> Int {
|
||||
let n = wgt.count
|
||||
// 初始化 dp 表
|
||||
@ -56,7 +56,7 @@ enum UnboundedKnapsack {
|
||||
var res = unboundedKnapsackDP(wgt: wgt, val: val, cap: cap)
|
||||
print("不超过背包容量的最大物品价值为 \(res)")
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = unboundedKnapsackDPComp(wgt: wgt, val: val, cap: cap)
|
||||
print("不超过背包容量的最大物品价值为 \(res)")
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ function climbingStairsDP(n: number): number {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
/* 爬楼梯:状态压缩后的动态规划 */
|
||||
/* 爬楼梯:空间优化后的动态规划 */
|
||||
function climbingStairsDPComp(n: number): number {
|
||||
if (n === 1 || n === 2) return n;
|
||||
let a = 1,
|
||||
|
@ -22,7 +22,7 @@ fn climbingStairsDP(comptime n: usize) i32 {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
// 爬楼梯:状态压缩后的动态规划
|
||||
// 爬楼梯:空间优化后的动态规划
|
||||
fn climbingStairsDPComp(comptime n: usize) i32 {
|
||||
if (n == 1 or n == 2) {
|
||||
return @intCast(n);
|
||||
|
@ -33,7 +33,7 @@ fn coinChangeDP(comptime coins: []i32, comptime amt: usize) i32 {
|
||||
}
|
||||
}
|
||||
|
||||
// 零钱兑换:状态压缩后的动态规划
|
||||
// 零钱兑换:空间优化后的动态规划
|
||||
fn coinChangeDPComp(comptime coins: []i32, comptime amt: usize) i32 {
|
||||
comptime var n = coins.len;
|
||||
comptime var max = amt + 1;
|
||||
@ -69,7 +69,7 @@ pub fn main() !void {
|
||||
var res = coinChangeDP(&coins, amt);
|
||||
std.debug.print("凑到目标金额所需的最少硬币数量为 {}\n", .{res});
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeDPComp(&coins, amt);
|
||||
std.debug.print("凑到目标金额所需的最少硬币数量为 {}\n", .{res});
|
||||
|
||||
|
@ -28,7 +28,7 @@ fn coinChangeIIDP(comptime coins: []i32, comptime amt: usize) i32 {
|
||||
return dp[n][amt];
|
||||
}
|
||||
|
||||
// 零钱兑换 II:状态压缩后的动态规划
|
||||
// 零钱兑换 II:空间优化后的动态规划
|
||||
fn coinChangeIIDPComp(comptime coins: []i32, comptime amt: usize) i32 {
|
||||
comptime var n = coins.len;
|
||||
// 初始化 dp 表
|
||||
@ -58,7 +58,7 @@ pub fn main() !void {
|
||||
var res = coinChangeIIDP(&coins, amt);
|
||||
std.debug.print("凑出目标金额的硬币组合数量为 {}\n", .{res});
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = coinChangeIIDPComp(&coins, amt);
|
||||
std.debug.print("凑出目标金额的硬币组合数量为 {}\n", .{res});
|
||||
|
||||
|
@ -88,7 +88,7 @@ fn editDistanceDP(comptime s: []const u8, comptime t: []const u8) i32 {
|
||||
return dp[n][m];
|
||||
}
|
||||
|
||||
// 编辑距离:状态压缩后的动态规划
|
||||
// 编辑距离:空间优化后的动态规划
|
||||
fn editDistanceDPComp(comptime s: []const u8, comptime t: []const u8) i32 {
|
||||
comptime var n = s.len;
|
||||
comptime var m = t.len;
|
||||
@ -138,7 +138,7 @@ pub fn main() !void {
|
||||
res = editDistanceDP(s, t);
|
||||
std.debug.print("将 {s} 更改为 {s} 最少需要编辑 {} 步\n", .{ s, t, res });
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = editDistanceDPComp(s, t);
|
||||
std.debug.print("将 {s} 更改为 {s} 最少需要编辑 {} 步\n", .{ s, t, res });
|
||||
|
||||
|
@ -63,7 +63,7 @@ fn knapsackDP(comptime wgt: []i32, val: []i32, comptime cap: usize) i32 {
|
||||
return dp[n][cap];
|
||||
}
|
||||
|
||||
// 0-1 背包:状态压缩后的动态规划
|
||||
// 0-1 背包:空间优化后的动态规划
|
||||
fn knapsackDPComp(wgt: []i32, val: []i32, comptime cap: usize) i32 {
|
||||
var n = wgt.len;
|
||||
// 初始化 dp 表
|
||||
@ -102,7 +102,7 @@ pub fn main() !void {
|
||||
res = knapsackDP(&wgt, &val, cap);
|
||||
std.debug.print("不超过背包容量的最大物品价值为 {}\n", .{res});
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = knapsackDPComp(&wgt, &val, cap);
|
||||
std.debug.print("不超过背包容量的最大物品价值为 {}\n", .{res});
|
||||
|
||||
|
@ -22,7 +22,7 @@ fn minCostClimbingStairsDP(comptime cost: []i32) i32 {
|
||||
return dp[n];
|
||||
}
|
||||
|
||||
// 爬楼梯最小代价:状态压缩后的动态规划
|
||||
// 爬楼梯最小代价:空间优化后的动态规划
|
||||
fn minCostClimbingStairsDPComp(cost: []i32) i32 {
|
||||
var n = cost.len - 1;
|
||||
if (n == 1 or n == 2) {
|
||||
|
@ -68,7 +68,7 @@ fn minPathSumDP(comptime grid: anytype) i32 {
|
||||
return dp[n - 1][m - 1];
|
||||
}
|
||||
|
||||
// 最小路径和:状态压缩后的动态规划
|
||||
// 最小路径和:空间优化后的动态规划
|
||||
fn minPathSumDPComp(comptime grid: anytype) i32 {
|
||||
comptime var n = grid.len;
|
||||
comptime var m = grid[0].len;
|
||||
@ -114,7 +114,7 @@ pub fn main() !void {
|
||||
res = minPathSumDP(&grid);
|
||||
std.debug.print("从左上角到右下角的最小路径和为 {}\n", .{res});
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = minPathSumDPComp(&grid);
|
||||
std.debug.print("从左上角到右下角的最小路径和为 {}\n", .{res});
|
||||
|
||||
|
@ -24,7 +24,7 @@ fn unboundedKnapsackDP(comptime wgt: []i32, val: []i32, comptime cap: usize) i32
|
||||
return dp[n][cap];
|
||||
}
|
||||
|
||||
// 完全背包:状态压缩后的动态规划
|
||||
// 完全背包:空间优化后的动态规划
|
||||
fn unboundedKnapsackDPComp(comptime wgt: []i32, val: []i32, comptime cap: usize) i32 {
|
||||
comptime var n = wgt.len;
|
||||
// 初始化 dp 表
|
||||
@ -54,7 +54,7 @@ pub fn main() !void {
|
||||
var res = unboundedKnapsackDP(&wgt, &val, cap);
|
||||
std.debug.print("不超过背包容量的最大物品价值为 {}\n", .{res});
|
||||
|
||||
// 状态压缩后的动态规划
|
||||
// 空间优化后的动态规划
|
||||
res = unboundedKnapsackDPComp(&wgt, &val, cap);
|
||||
std.debug.print("不超过背包容量的最大物品价值为 {}\n", .{res});
|
||||
|
||||
|
@ -110,7 +110,7 @@ $$
|
||||
|
||||

|
||||
|
||||
本题也可以进行状态压缩,将一维压缩至零维,使得空间复杂度从 $O(n)$ 降低至 $O(1)$ 。
|
||||
本题也可以进行空间优化,将一维压缩至零维,使得空间复杂度从 $O(n)$ 降低至 $O(1)$ 。
|
||||
|
||||
=== "Java"
|
||||
|
||||
|
@ -374,7 +374,7 @@ $$
|
||||
=== "<12>"
|
||||

|
||||
|
||||
### 状态压缩
|
||||
### 空间优化
|
||||
|
||||
由于每个格子只与其左边和上边的格子有关,因此我们可以只用一个单行数组来实现 $dp$ 表。
|
||||
|
||||
|
@ -186,7 +186,7 @@ $$
|
||||
=== "<15>"
|
||||

|
||||
|
||||
### 状态压缩
|
||||
### 空间优化
|
||||
|
||||
由于 $dp[i,j]$ 是由上方 $dp[i-1, j]$ 、左方 $dp[i, j-1]$ 、左上方状态 $dp[i-1, j-1]$ 转移而来,而正序遍历会丢失左上方 $dp[i-1, j-1]$ ,倒序遍历无法提前构建 $dp[i, j-1]$ ,因此两种遍历顺序都不可取。
|
||||
|
||||
|
@ -442,7 +442,7 @@ $$
|
||||
- 将最小子问题对应的状态(即第 $1$ , $2$ 阶楼梯)称为「初始状态」。
|
||||
- 将递推公式 $dp[i] = dp[i-1] + dp[i-2]$ 称为「状态转移方程」。
|
||||
|
||||
## 状态压缩
|
||||
## 空间优化
|
||||
|
||||
细心的你可能发现,**由于 $dp[i]$ 只与 $dp[i-1]$ 和 $dp[i-2]$ 有关,因此我们无须使用一个数组 `dp` 来存储所有子问题的解**,而只需两个变量滚动前进即可。
|
||||
|
||||
@ -520,4 +520,4 @@ $$
|
||||
|
||||
观察以上代码,由于省去了数组 `dp` 占用的空间,因此空间复杂度从 $O(n)$ 降低至 $O(1)$ 。
|
||||
|
||||
**这种空间优化技巧被称为「状态压缩」**。在常见的动态规划问题中,当前状态仅与前面有限个状态有关,这时我们可以应用状态压缩,只保留必要的状态,通过“降维”来节省内存空间。
|
||||
在动态规划问题中,当前状态往往仅与前面有限个状态有关,这时我们可以只保留必要的状态,通过“降维”来节省内存空间。**这种空间优化技巧被称为“滚动变量”或“滚动数组”**。
|
||||
|
@ -336,11 +336,11 @@ $$
|
||||
=== "<14>"
|
||||

|
||||
|
||||
### 状态压缩
|
||||
### 空间优化
|
||||
|
||||
由于每个状态都只与其上一行的状态有关,因此我们可以使用两个数组滚动前进,将空间复杂度从 $O(n^2)$ 将低至 $O(n)$ 。
|
||||
|
||||
进一步思考,我们是否可以仅用一个数组实现状态压缩呢?观察可知,每个状态都是由正上方或左上方的格子转移过来的。假设只有一个数组,当开始遍历第 $i$ 行时,该数组存储的仍然是第 $i-1$ 行的状态。
|
||||
进一步思考,我们是否可以仅用一个数组实现空间优化呢?观察可知,每个状态都是由正上方或左上方的格子转移过来的。假设只有一个数组,当开始遍历第 $i$ 行时,该数组存储的仍然是第 $i-1$ 行的状态。
|
||||
|
||||
- 如果采取正序遍历,那么遍历到 $dp[i, j]$ 时,左上方 $dp[i-1, 1]$ ~ $dp[i-1, j-1]$ 值可能已经被覆盖,此时就无法得到正确的状态转移结果。
|
||||
- 如果采取倒序遍历,则不会发生覆盖问题,状态转移可以正确进行。
|
||||
@ -348,7 +348,7 @@ $$
|
||||
下图展示了在单个数组下从第 $i = 1$ 行转换至第 $i = 2$ 行的过程。请思考正序遍历和倒序遍历的区别。
|
||||
|
||||
=== "<1>"
|
||||

|
||||

|
||||
|
||||
=== "<2>"
|
||||

|
||||
|
@ -11,8 +11,8 @@
|
||||
**背包问题**
|
||||
|
||||
- 背包问题是最典型的动态规划题目,具有 0-1 背包、完全背包、多重背包等变种问题。
|
||||
- 0-1 背包的状态定义为前 $i$ 个物品在剩余容量为 $c$ 的背包中的最大价值。根据不放入背包和放入背包两种决策,可得到最优子结构,并构建出状态转移方程。在状态压缩中,由于每个状态依赖正上方和左上方的状态,因此需要倒序遍历列表,避免左上方状态被覆盖。
|
||||
- 完全背包的每种物品的选取数量无限制,因此选择放入物品的状态转移与 0-1 背包不同。由于状态依赖于正上方和正左方的状态,因此在状态压缩中应当正序遍历。
|
||||
- 0-1 背包的状态定义为前 $i$ 个物品在剩余容量为 $c$ 的背包中的最大价值。根据不放入背包和放入背包两种决策,可得到最优子结构,并构建出状态转移方程。在空间优化中,由于每个状态依赖正上方和左上方的状态,因此需要倒序遍历列表,避免左上方状态被覆盖。
|
||||
- 完全背包的每种物品的选取数量无限制,因此选择放入物品的状态转移与 0-1 背包不同。由于状态依赖于正上方和正左方的状态,因此在空间优化中应当正序遍历。
|
||||
- 零钱兑换问题是完全背包的一个变种。它从求“最大”价值变为求“最小”硬币数量,因此状态转移方程中的 $\max()$ 应改为 $\min()$ 。从求“不超过”背包容量到求“恰好”凑出目标金额,因此使用 $amt + 1$ 来表示“无法凑出目标金额”的无效解。
|
||||
- 零钱兑换 II 问题从求“最少硬币数量”改为求“硬币组合数量”,状态转移方程相应地从 $\min()$ 改为求和运算符。
|
||||
|
||||
@ -20,4 +20,4 @@
|
||||
|
||||
- 编辑距离(Levenshtein 距离)用于衡量两个字符串之间的相似度,其定义为从一个字符串到另一个字符串的最小编辑步数,编辑操作包括添加、删除、替换。
|
||||
- 编辑距离问题的状态定义为将 $s$ 的前 $i$ 个字符更改为 $t$ 的前 $j$ 个字符所需的最少编辑步数。当 $s[i] \ne t[j]$ 时,具有三种决策:添加、删除、替换,它们都有相应的剩余子问题。据此便可以找出最优子结构与构建状态转移方程。而当 $s[i] = t[j]$ 时,无须编辑当前字符。
|
||||
- 在编辑距离中,状态依赖于其正上方、正左方、左上方的状态,因此状态压缩后正序或倒序遍历都无法正确地进行状态转移。为此,我们利用一个变量暂存左上方状态,从而转化到与完全背包等价的情况,可以在状态压缩后进行正序遍历。
|
||||
- 在编辑距离中,状态依赖于其正上方、正左方、左上方的状态,因此空间优化后正序或倒序遍历都无法正确地进行状态转移。为此,我们利用一个变量暂存左上方状态,从而转化到与完全背包等价的情况,可以在空间优化后进行正序遍历。
|
||||
|
@ -104,14 +104,14 @@ $$
|
||||
[class]{}-[func]{unbounded_knapsack_dp}
|
||||
```
|
||||
|
||||
### 状态压缩
|
||||
### 空间优化
|
||||
|
||||
由于当前状态是从左边和上边的状态转移而来,**因此状态压缩后应该对 $dp$ 表中的每一行采取正序遍历**。
|
||||
由于当前状态是从左边和上边的状态转移而来,**因此空间优化后应该对 $dp$ 表中的每一行采取正序遍历**。
|
||||
|
||||
这个遍历顺序与 0-1 背包正好相反。请借助下图来理解两者的区别。
|
||||
|
||||
=== "<1>"
|
||||

|
||||

|
||||
|
||||
=== "<2>"
|
||||

|
||||
@ -370,9 +370,9 @@ $$
|
||||
=== "<15>"
|
||||

|
||||
|
||||
### 状态压缩
|
||||
### 空间优化
|
||||
|
||||
零钱兑换的状态压缩的处理方式和完全背包一致。
|
||||
零钱兑换的空间优化的处理方式和完全背包一致。
|
||||
|
||||
=== "Java"
|
||||
|
||||
@ -540,9 +540,9 @@ $$
|
||||
[class]{}-[func]{coin_change_ii_dp}
|
||||
```
|
||||
|
||||
### 状态压缩
|
||||
### 空间优化
|
||||
|
||||
状态压缩处理方式相同,删除硬币维度即可。
|
||||
空间优化处理方式相同,删除硬币维度即可。
|
||||
|
||||
=== "Java"
|
||||
|
||||
|
@ -2,17 +2,25 @@
|
||||
|
||||
在某些情况下,我们希望使用一个列表的所有元素来构建一个堆,这个过程被称为“建堆操作”。
|
||||
|
||||
## 借助入堆方法实现
|
||||
## 自上而下构建
|
||||
|
||||
最直接的方法是借助“元素入堆操作”实现。我们首先创建一个空堆,然后将列表元素依次执行“入堆”。
|
||||
我们首先创建一个空堆,然后遍历列表,依次对每个元素执行“入堆操作”,即先将元素添加至堆的尾部,再对该元素执行“从底至顶”堆化。
|
||||
|
||||
设元素数量为 $n$ ,入堆操作使用 $O(\log{n})$ 时间,因此将所有元素入堆的时间复杂度为 $O(n \log n)$ 。
|
||||
每当一个元素入堆,堆的长度就加一,因此堆是“自上而下”地构建的。
|
||||
|
||||
## 基于堆化操作实现
|
||||
设元素数量为 $n$ ,每个元素的入堆操作使用 $O(\log{n})$ 时间,因此该建堆方法的时间复杂度为 $O(n \log n)$ 。
|
||||
|
||||
有趣的是,存在一种更高效的建堆方法,其时间复杂度可以达到 $O(n)$ 。我们先将列表所有元素原封不动添加到堆中,然后倒序遍历该堆,依次对每个节点执行“从顶至底堆化”。
|
||||
## 自下而上构建
|
||||
|
||||
请注意,因为叶节点没有子节点,所以无须堆化。在代码实现中,我们从最后一个节点的父节点开始进行堆化。
|
||||
实际上,我们可以实现一种更为高效的建堆方法,共分为两步。
|
||||
|
||||
1. 将列表所有元素原封不动添加到堆中。
|
||||
2. 倒序遍历堆(即层序遍历的倒序),依次对每个非叶节点执行“从顶至底堆化”。
|
||||
|
||||
在倒序遍历中,堆是“自下而上”地构建的,需要重点理解以下两点。
|
||||
|
||||
- 由于叶节点没有子节点,因此无需对它们执行堆化。最后一个节点的父节点是最后一个非叶节点。
|
||||
- 在倒序遍历中,我们能够保证当前节点之下的子树已经完成堆化(已经是合法的堆),而这是堆化当前节点的前置条件。
|
||||
|
||||
=== "Java"
|
||||
|
||||
@ -88,24 +96,24 @@
|
||||
|
||||
## 复杂度分析
|
||||
|
||||
为什么第二种建堆方法的时间复杂度是 $O(n)$ ?我们来展开推算一下。
|
||||
下面,我们来尝试推算第二种建堆方法的时间复杂度。
|
||||
|
||||
- 在完全二叉树中,设节点总数为 $n$ ,则叶节点数量为 $(n + 1) / 2$ ,其中 $/$ 为向下整除。因此,在排除叶节点后,需要堆化的节点数量为 $(n - 1)/2$ ,复杂度为 $O(n)$ 。
|
||||
- 在从顶至底堆化的过程中,每个节点最多堆化到叶节点,因此最大迭代次数为二叉树高度 $O(\log n)$ 。
|
||||
- 假设完全二叉树的节点数量为 $n$ ,则叶节点数量为 $(n + 1) / 2$ ,其中 $/$ 为向下整除。因此需要堆化的节点数量为 $(n - 1) / 2$ 。
|
||||
- 在从顶至底堆化的过程中,每个节点最多堆化到叶节点,因此最大迭代次数为二叉树高度 $\log n$ 。
|
||||
|
||||
将上述两者相乘,可得到建堆过程的时间复杂度为 $O(n \log n)$ 。**然而,这个估算结果并不准确,因为我们没有考虑到二叉树底层节点数量远多于顶层节点的特性**。
|
||||
将上述两者相乘,可得到建堆过程的时间复杂度为 $O(n \log n)$ 。**但这个估算结果并不准确,因为我们没有考虑到二叉树底层节点数量远多于顶层节点的性质**。
|
||||
|
||||
接下来我们来进行更为详细的计算。为了减小计算难度,我们假设树是一个“完美二叉树”,该假设不会影响计算结果的正确性。设二叉树(即堆)节点数量为 $n$ ,树高度为 $h$ 。
|
||||
接下来我们来进行更为准确的计算。为了减小计算难度,假设给定一个节点数量为 $n$ ,高度为 $h$ 的“完美二叉树”,该假设不会影响计算结果的正确性。
|
||||
|
||||

|
||||
|
||||
如上图所示,**节点“从顶至底堆化”的最大迭代次数等于该节点到叶节点的距离,而该距离正是“节点高度”**。因此,我们可以将各层的“节点数量 $\times$ 节点高度”求和,**从而得到所有节点的堆化迭代次数的总和**。
|
||||
如上图所示,节点“从顶至底堆化”的最大迭代次数等于该节点到叶节点的距离,而该距离正是“节点高度”。因此,我们可以将各层的“节点数量 $\times$ 节点高度”求和,**从而得到所有节点的堆化迭代次数的总和**。
|
||||
|
||||
$$
|
||||
T(h) = 2^0h + 2^1(h-1) + 2^2(h-2) + \dots + 2^{(h-1)}\times1
|
||||
$$
|
||||
|
||||
化简上式需要借助中学的数列知识,先对 $T(h)$ 乘以 $2$ ,得到
|
||||
化简上式需要借助中学的数列知识,先对 $T(h)$ 乘以 $2$ ,得到:
|
||||
|
||||
$$
|
||||
\begin{aligned}
|
||||
@ -114,13 +122,13 @@ T(h) & = 2^0h + 2^1(h-1) + 2^2(h-2) + \dots + 2^{h-1}\times1 \newline
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
使用错位相减法,用下式 $2 T(h)$ 减去上式 $T(h)$ ,可得
|
||||
使用错位相减法,用下式 $2 T(h)$ 减去上式 $T(h)$ ,可得:
|
||||
|
||||
$$
|
||||
2T(h) - T(h) = T(h) = -2^0h + 2^1 + 2^2 + \dots + 2^{h-1} + 2^h
|
||||
$$
|
||||
|
||||
观察上式,发现 $T(h)$ 是一个等比数列,可直接使用求和公式,得到时间复杂度为
|
||||
观察上式,发现 $T(h)$ 是一个等比数列,可直接使用求和公式,得到时间复杂度为:
|
||||
|
||||
$$
|
||||
\begin{aligned}
|
||||
|
Loading…
x
Reference in New Issue
Block a user