前言
更詳細的在大佬的代碼隨想錄 (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];//返回全部遍歷后的最大值}
};