003 动态规划
是什么
动态规划的思想通过解决了一个一个简单的问题,进而把简单的问题的解组成了复杂的问题的解。
是用哈希表保存中间结果, 避免重复节点的计算的一种优化方法. 也叫记忆化搜索/递归树的剪枝(pruning).
- 特点:空间换时间
为什么
什么时候用动态规划?
股票买卖等 求最值 问题
怎么样
70. 爬楼梯
暴力递归, 把最大值放进去测试, 超时
class Solution {
public:
int climbStairs(int n) {
//递归 最后如果剩下1, 一种, 最后如果剩下2, 2种
if(n==1) return 1;
if(n==2) return 2;
//第一级台阶要么跳1阶, 要么跳2阶
return climbStairs(n-1)+climbStairs(n-2);
}
};
动态规划
class Solution
{
public:
int climbStairs(int n)
{
vector<int> dp(46);
dp[0] = 1;
dp[1] = 1;
for(int i = 2;i<n+1;i++)
{
dp[i] = dp[i-1]+dp[i-2];
}
return dp[n];
}
};
优化空间
ps: 类似的题还有求斐波那契数列那题, 两者都可以直接套公式, 也可以用对角矩阵计算
53. 最大子数组和
动态规划
class Solution {
public:
int maxSubArray(vector<int>& nums) {
//「状态定义」
vector<int> dp(nums.size());
dp[0] = nums[0];
int result = dp[0];
//「状态转移方程」如果dp[i-1]<=0, 从dp[i] = nums[i]
for(int i = 1;i<nums.size();i++)
{
if(dp[i-1]<=0) dp[i] = nums[i];
else dp[i] = dp[i-1]+nums[i];
result = max(result,dp[i]);
}
//「初始化」
//「输出」
return result;
//「是否可以空间优化」
}
};
空间优化
class Solution {
public:
int maxSubArray(vector<int>& nums) {
int pre = 0; //注意这里是 0
int res = nums[0];
for(int i:nums)
{
pre = max(pre+i,i);
res = max(pre,res);
}
return res;
}
};
总结:
1 找出 无后效性
的子问题
2 写出 状态转移方程
3 是否可以空间优化(解题的时候可以但没必要)
tips:「状态定义」「状态转移方程」「初始化」「输出」「是否可以空间优化」全都写出来