动态规划
解题框架
明确「状态」 -> 定义 dp 数组/函数的含义 -> 明确「选择」-> 明确 base case。
自顶向下
通过递归树而从上向下延伸的解题方式,一般用递归来解题。
框架
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| function coinChange(coins: List[int], amount: int) { const dpTable = {}; function dp(n) { if (dpTable[n]) return dpTable[n]; if (n === 0) return 0; if (n < 0) return -1; let res = Number.POSITIVE_INFINITY; const coinsLen = coins.length; for (let i = 0; i < coinsLen; i++) { const num = dp(n - coins[i]); if (num === -1) continue; res = Math.min(res, 1 + num); } dpTable[n] = res === Number.POSITIVE_INFINITY ? -1 : res; return dpTable[n]; }
return dp(amount); }
|
自底向上
从递归树最底下往上推出来的解题方式,一般用循环迭代来解题。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| function jump(nums: number[]): number { const dp: number[] = Array.from(Array(nums.length), () => { return nums.length + 1; }); dp[0] = 0; for (let i = 0; i < dp.length; i++) { for (let j = 1; j <= nums[i]; j++) { if (i + j >= nums.length) return dp[dp.length - 1]; dp[i + j] = Math.min(dp[i + j], 1 + dp[i]); } } return dp[dp.length - 1]; }
|