建设部门户网站条例免费下载/2345网址导航主页
1. 动态规划
动规五部曲
- 确定dp数组(dp table)以及下标的含义
- 确定递推公式
- dp数组如何初始化
- 确定遍历顺序
- 打印dp数组
每次写动态规划题要考虑清楚这五步,特别是每一步为什么这么写,才算掌握了一道题。
2. 斐波那契数
力扣
class Solution {public int fib(int n) {if(n <= 1) return n;int[] nums = new int[n + 1];nums[0] = 0;nums[1] = 1;for(int i = 2; i <= n; i++){nums[i] = nums[i - 1] + nums[i - 2];}return nums[n];}
}
还可以做空间优化
class Solution {public int fib(int n) {if (n < 2) return n;int a = 0, b = 1, c = 0;for (int i = 1; i < n; i++) {c = a + b;a = b;b = c;}return c;}
}
递归写法
class Solution {
public:int fib(int N) {if (N < 2) return N;return fib(N - 1) + fib(N - 2);}
};
3. 爬楼梯
力扣
从到达第i层台阶有两种方法:从i-2走两步或者i-1走一步。令dp[i]表示走到第i层的所有方法,那么dp[i]就是dp[i - 1]和dp[i - 2]的总和。
class Solution {public int climbStairs(int n) {if(n <= 2) return n;//dp[i]:爬到第i层楼有几种解法int[] dp = new int[n + 1];dp[1] = 1;dp[2] = 2;for(int i = 3; i <= n; i++){dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];}
}
dp[0]的初始化没有意义,因为题目说明了从1开始。为了代码的统一性也可以从0开始:
public int climbStairs(int n) {int[] dp = new int[n + 1];dp[0] = 1;dp[1] = 1;for (int i = 2; i <= n; i++) {dp[i] = dp[i - 1] + dp[i - 2];}return dp[n];
}
4. 使用最小花费爬楼梯
力扣
dp[i]的定义:到达第i台阶所花费的最少体力为dp[i]。
可以有两个途径得到dp[i],一个是dp[i-1] 一个是dp[i-2]。
dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。
dp[i - 2] 跳到 dp[i] 需要花费 dp[i - 2] + cost[i - 2]。
选最小的,所以dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2])。
题目中表述为:可以从0层或1层开始,证明可以初始化 dp[0] = 0,dp[1] = 0。
class Solution {public int minCostClimbingStairs(int[] cost) {int n = cost.length;int[] dp = new int[n + 1];dp[0] = 0;dp[1] = 0;for(int i = 2; i <= n; i++){dp[i] = Math.min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);}return dp[n];}
}