本博客是记录作者做动态规划算法的简单、中等难度的背包问题的笔记。
LeetCode题目 | 相关题目类型 | 题目类型分析 | 题目思路 | 相关链接 |
---|---|---|---|---|
0416 | 分割等和子集(中等难度) | 416. 分割等和子集 - 力扣(LeetCode) (leetcode-cn.com) | ||
1049 | 最后一块石头的重量II(中等难度) | 1049. 最后一块石头的重量 II - 力扣(LeetCode) (leetcode-cn.com) | ||
0494 | 目标和(中等难度) | 494. 目标和 - 力扣(LeetCode) (leetcode-cn.com) | ||
0474 | 一和零(中等难度) | 474. 一和零 - 力扣(LeetCode) (leetcode-cn.com) | ||
0518 | 零钱兑换II(中等难度) | 518. 零钱兑换 II - 力扣(LeetCode) (leetcode-cn.com) | ||
0377 | 组合总和IV(中等难度) | 377. 组合总和 Ⅳ - 力扣(LeetCode) (leetcode-cn.com) | ||
0070 | 爬楼梯(简单难度) | 70. 爬楼梯 - 力扣(LeetCode) (leetcode-cn.com) | ||
0322 | 零钱兑换(中等难度) | 322. 零钱兑换 - 力扣(LeetCode) (leetcode-cn.com) | ||
0279 | 完全平方数(中等难度) | 279. 完全平方数 - 力扣(LeetCode) (leetcode-cn.com) | ||
0139 | 单词拆分(中等难度) | 139. 单词拆分 - 力扣(LeetCode) (leetcode-cn.com) |
121 买卖股票的最佳时机
动规五部曲:
这里我们要用一个一维dp数组来保存递归的结果
1、确定dp数组以及下标的含义
dp[i]的定义为:第i个数的斐波那契数值是dp[i]
2、确定递推公式
题目已经把递推公式直接给我们了:状态转移方程 dp[i] = dp[i - 1] + dp[i - 2]
3、dp数组如何初始化
dp[0] = 0;
dp[1] = 1;
4、确定遍历顺序
从递归公式dp[i] = dp[i - 1] + dp[i - 2];中可以看出,dp[i]是依赖 dp[i - 1] 和 dp[i - 2],那么遍历的顺序一定是从前到后遍历的
5、举例推导dp数组
按照这个递推公式dp[i] = dp[i - 1] + dp[i - 2],我们来推导一下,当N为10的时候,dp数组应该是如下的数列:
0 1 1 2 3 5 8 13 21 34 55
如果代码写出来,发现结果不对,就把dp数组打印出来看看和我们推导的数列是不是一致的。
以上我们用动规的方法分析完了,C++代码如下:
int fib(int n) {
/*输入一个整数,输出一个整数*/
if(n<=1){
return n;
}
vector<int> dp(n+1); //第i个数的斐波那契数值是dp[i]
dp[0]=0;
dp[1]=1;
for(int i=2;i<n+1;i++){
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n];
}
当然可以发现,我们只需要维护两个数值就可以了,不需要记录整个序列。代码如下:
int fib(int n) {
/*输入一个整数,输出一个整数*/
if(n<=1){
return n;
}
vector<int> dp(2); //第i个数的斐波那契数值是dp[i]
dp[0]=0;
dp[1]=1;
for(int i=2;i<n+1;i++){
int temp = dp[0]+dp[1];
dp[0] = dp[1];
dp[1] = temp;
}
return dp[1];
}