理论基础
题型
- 动归基础(这一节就是基础题)
- 背包问题
- 打家劫舍
- 股票问题
- 子序列问题
动态规划五部曲
- 确定dp数组及其下标的含义
- 确定递推公式
- dp数组如何初始化
- 遍历顺序
- 打印dp数组
509. 斐波那契数
简单~
- dp数组及下标含义: dp[i]表示第i各斐波那契数,值为dp[i]
- 递推公式:dp[i] = dp[i-1] -dp[i-2]
- dp数组如何初始化:dp[0] = 0; dp[1] = 1;题目描述中有敌意
- 遍历顺序:从前往后
- 打印dp数组
当前位置的值只与该位置的前两个数值有关,只需要维护长度为2的数组。
class Solution {
public:
int fib(int n) {
if(n==0 || n==1) return n;
vector<int> dp(2);
dp[0] = 0; dp[1] = 1;
for(int i=2; i<=n; i++){
int sum = dp[1] + dp[0];
dp[0] = dp[1];
dp[1] = sum;
}
return dp[1];
}
};
class Solution {
public int fib(int n) {
if(n == 0 || n == 1) return n;
int[] dp = new int[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];
}
}
class Solution(object):
def fib(self, n):
"""
:type n: int
:rtype: int
"""
if n == 0 or n == 1:
return n
dp = [0,1]
for i in range(2, n+1):
sum_ = dp[0] + dp[1]
dp[0] = dp[1]
dp[1] = sum_
return dp[1]
参考文章
70. 爬楼梯
要明白如果爬n层有两种情况: 一种是从n-2层迈两步上来的,一种是从n-1层迈一步上来的。所以到达第n层的方法数量=到达第n-2层的方法数+到达第n-1层的方法数。
- dp数组及其下标含义 dp[i] 表示到达第i层的方法数量
- 递推公式 dp[i] = dp[i-1] + dp[i-2]
- dp数组初始化 dp[1] = 1 dp[2] = 2,0没有实际意义
- 遍历顺序:从前往后
- 打印dp数组
当前位置数值只与当前位置前2个位置数值有关,只需要维护长度为2的数组,但是0没有实际意义,为了实现更加明确的初始化我们定义长度为3的数组,0这个位置不进行初始化。
class Solution {
public:
int climbStairs(int n) {
if(n==1 || n==2) return n;
vector<int> dp(3);
dp[1] = 1;//空出0来因为没有意义
dp[2] = 2;
for(int i = 3; i <= n; i++){
int sum = dp[1] + dp[2];
dp[1] = dp[2];
dp[2] = sum;
}
return dp[2];
}
};
class Solution {
public int climbStairs(int n) {
if(n == 1 || n == 2) return n;
int[] dp = new int[3];
dp[1] = 1; dp[2] = 2;
for(int i = 3; i <= n; i++){
int sum = dp[1] + dp[2];
dp[1] = dp[2];
dp[2] = sum;
}
return dp[2];
}
}
class Solution(object):
def climbStairs(self, n):
"""
:type n: int
:rtype: int
"""
if n == 1 or n == 2:
return n
dp = [None, 1, 2]
for i in range(3, n+1):
sum_ = dp[1] + dp[2]
dp[1] = dp[2]
dp[2] = sum_
return dp[2]
参考文章
746. 使用最小花费爬楼梯
Note:注意题目描述,该位置不花费体力,往上跳花费体力。并且cost的长度是顶楼。
- dp数组及其下标含义:dp[i] 到达第i层所需要的最小花费为dp[i]
- 递推公式: dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2]);
- dp数组如何初始化: dp[0]=0;dp[1]=0;//因为当前位置不花费,向上跳才花费所以都初始化为0
- 遍历顺序:从前往后
- 打印dp数组
class Solution {
public:
int minCostClimbingStairs(vector<int>& cost) {
if(cost.size()<2) return 0;
vector<int> dp(2);
for(int i = 2; i <= cost.size(); i++){
int minCost = min(dp[0] + cost[i-2], dp[1] + cost[i-1]);
dp[0] = dp[1];
dp[1] = minCost;
}
return dp[1];
}
};
class Solution {
public int minCostClimbingStairs(int[] cost) {
if(cost.length<2) return 0;
int[] dp = new int[]{0, 0};
for(int i = 2; i <= cost.length; i++){
int minCost = Math.min(dp[0] + cost[i-2], dp[1] + cost[i-1]);
dp[0] = dp[1];
dp[1] = minCost;
}
return dp[1];
}
}
class Solution(object):
def minCostClimbingStairs(self, cost):
"""
:type cost: List[int]
:rtype: int
"""
if len(cost)<2:
return 0
dp = [0, 0]
for i in range(2, len(cost)+1):
minCost = min(dp[0]+cost[i-2], dp[1]+cost[i-1])
dp[0] = dp[1]
dp[1] = minCost
return dp[1]