前言
更详细的在大佬的代码随想录 (programmercarl.com)
本系列仅是简洁版笔记,为了之后方便观看
做题步骤
含义公式初始化顺序检查
- 确定dp数组以及下标的含义
- 递推公式
- dp数组如何初始化
- 遍历顺序
- 打印dp数组(看哪里有问题)
斐波那契数
class Solution {
public:int fib(int n) {if(n<=1) return n;int dp[2];dp[0]=0;dp[1]=1;for(int i=2;i<=n;i++){int sum = dp[0] + dp[1];dp[0] = dp[1];dp[1] = sum;}return dp[1];}
};
爬楼梯
70. 爬楼梯 - 力扣(LeetCode)
代码思路和上一题相差不大,主要是初始化和遍历时i的取值不同。
class Solution {
public:int climbStairs(int n) {if (n <= 1) return n; vector<int> dp(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];}
};
使用最小花费爬楼梯
746. 使用最小花费爬楼梯 - 力扣(LeetCode)
爬楼梯的消费版
dp表示的是到达本层已经使用的体力,cost[i] 是从本台阶向上爬需要支付的费用
class Solution {
public:int minCostClimbingStairs(vector<int>& cost) {vector<int> dp(cost.size() + 1);dp[0] = 0;//根据题意设计dp[1] = 0;for (int i = 2; i <= cost.size(); i++) {dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);}return dp[cost.size()];}
};
不同路径
62. 不同路径 - 力扣(LeetCode)
题意:只能向下向右到目标地点,求路径数
dp[i][j] 只和 dp[i - 1][j] 和dp[i][j - 1]有关,很容易造成的观点错误是dp[i - 1][j]+1和dp[i][j - 1]推导而来,但是要清楚的是本题求得是路径数,dp[i - 1][j] 只能向下走,dp[i][j - 1]只能向右走,所以路径数不变
class Solution {
public:int uniquePaths(int m, int n) {vector<vector<int>>dp(m,vector<int>(n,0));for (int i = 0; i < m; i++) dp[i][0] = 1;for (int j = 0; j < n; j++) dp[0][j] = 1;for (int i = 1; i < m; i++) {for (int j = 1; j < n; j++) {dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}return dp[m - 1][n - 1];}
};
不同路径 II
和上一题的不同点:障碍物的出现
代码不同点:遍历顺序添加限制条件,不同路径初始化要改变
没有障碍物的时候才可以正常遍历
if (obstacleGrid[i][j] == 0) { dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
}
vector<vector<int>> dp(m, vector<int>(n, 0));
for (int i = 0; i < m && obstacleGrid[i][0] == 0; i++) dp[i][0] = 1;
for (int j = 0; j < n && obstacleGrid[0][j] == 0; j++) dp[0][j] = 1;
整数拆分
. - 力扣(LeetCode)
拆成若干数使得相乘最大
技巧:拆分成多个近似相等的数
难思考点:遍历顺序
j * (i - j) :把整数拆分为两个数相乘,
j * dp[i - j]:拆分成两个以及两个以上的个数相乘
for (int i = 3; i <= n ; i++) {for (int j = 1; j < i - 1; j++) {dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));}
}
class Solution {
public:int integerBreak(int n) {vector<int> dp(n + 1);dp[2] = 1;//dp[0]和dp[1]都是0 因为不需要拆分for (int i = 3; i <= n ; i++) {for (int j = 1; j <= i / 2; j++) {dp[i] = max(dp[i], max((i - j) * j, dp[i - j] * j));//求取最大值}return dp[n];//返回全部遍历后的最大值}
};