赞
踩
明确 base case -> 明确「状态」-> 明确「选择」 -> 定义 dp 数组/函数的含义。
**#参考labuladong算法教程**
# 初始化 base case
dp[0][0][...] = base
# 进行状态转移
for 状态1 in 状态1的所有取值:
for 状态2 in 状态2的所有取值:
for ...
dp[状态1][状态2][...] = 求最值(选择1,选择2...)
1. 暴力递归
2. 带备忘录递归
3. dp数组的迭代解法
/*暴力递归*/ int fib(int N) { if (N == 1 || N == 2) return 1; return fib(N - 1) + fib(N - 2); } /*带备忘录递归*/ int fib(int N) { if (N < 1) return 0; // 备忘录全初始化为 0 vector<int> memo(N + 1, 0); // 进行带备忘录的递归 return helper(memo, N); } int helper(vector<int>& memo, int n) { // base case if (n == 1 || n == 2) return 1; // 已经计算过 if (memo[n] != 0) return memo[n]; memo[n] = helper(memo, n - 1) + helper(memo, n - 2); return memo[n]; } /*dp数组迭代*/ int fib(int N) { vector<int> dp(N + 1, 0); // base case dp[1] = dp[2] = 1; for (int i = 3; i <= N; i++) dp[i] = dp[i - 1] + dp[i - 2]; return dp[N]; } /*状态压缩:将空间复杂度降低*/ int fib(int n) { if (n == 2 || n == 1) return 1; int prev = 1, curr = 1; for (int i = 3; i <= n; i++) { int sum = prev + curr; prev = curr; curr = sum; } return curr; }
/*暴力递归*/ def coinChange(coins: List[int], amount: int): def dp(n): # base case if n == 0: return 0 if n < 0: return -1 # 求最小值,所以初始化为正无穷 res = float('INF') for coin in coins: subproblem = dp(n - coin) # 子问题无解,跳过 if subproblem == -1: continue res = min(res, 1 + subproblem) return res if res != float('INF') else -1 return dp(amount) /*带备忘录递归*/ def coinChange(coins: List[int], amount: int): # 备忘录 memo = dict() def dp(n): # 查备忘录,避免重复计算 if n in memo: return memo[n] # base case if n == 0: return 0 if n < 0: return -1 res = float('INF') for coin in coins: subproblem = dp(n - coin) if subproblem == -1: continue res = min(res, 1 + subproblem) # 记入备忘录 memo[n] = res if res != float('INF') else -1 return memo[n] return dp(amount) /*dp数组迭代*/ int coinChange(vector<int>& coins, int amount) { // 数组大小为 amount + 1,初始值也为 amount + 1 vector<int> dp(amount + 1, amount + 1); // base case dp[0] = 0; // 外层 for 循环在遍历所有状态的所有取值 for (int i = 0; i < dp.size(); i++) { // 内层 for 循环在求所有选择的最小值 for (int coin : coins) { // 子问题无解,跳过 if (i - coin < 0) continue; dp[i] = min(dp[i], 1 + dp[i - coin]); } } return (dp[amount] == amount + 1) ? -1 : dp[amount]; } /*状态压缩:将空间复杂度降低*/ int fib(int n) { if (n == 2 || n == 1) return 1; int prev = 1, curr = 1; for (int i = 3; i <= n; i++) { int sum = prev + curr; prev = curr; curr = sum; } return curr; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。