动态规划(Dynamic Programming,简称 DP)是一种在数学、计算机科学和经济学等领域中使用的算法设计技术。它通常用于优化问题,通过将问题分解为更小的子问题,以避免重复计算,并利用子问题的解构建原问题的解。
动态规划的基本思想是将原问题分解为相互重叠的子问题,通过求解和存储子问题的解,避免重复计算,从而提高算法效率。动态规划通常包括以下步骤:
- 定义状态: 将原问题划分为子问题,并定义每个子问题的状态。状态是问题的描述,可以包括需要求解的变量。
- 找到状态转移方程: 确定子问题之间的递推关系,即状态转移方程。状态转移方程描述了子问题之间的关系,从而可以通过已解决的子问题的解来求解新的子问题。
- 初始化: 设置初始状态的值,通常是问题规模较小时的简单情况。
- 递推计算: 使用状态转移方程进行递推计算,求解问题的最优解。
- 返回结果: 根据最终的状态,得到原问题的解。
1、题目描述
假设你正在爬楼梯。需要 n
阶你才能到达楼顶。
每次你可以爬 1
或 2
个台阶。你有多少种不同的方法可以爬到楼顶呢?
示例 1:
输入:n = 2
输出:2
解释:有两种方法可以爬到楼顶。
1. 1 阶 + 1 阶
2. 2 阶
示例 2:
输入:n = 3
输出:3
解释:有三种方法可以爬到楼顶。
1. 1 阶 + 1 阶 + 1 阶
2. 1 阶 + 2 阶
3. 2 阶 + 1 阶
2、分析
- 定义状态: 令
dp[i]
表示爬到第i
个楼梯的不同爬法。 - 找到状态转移方程: 由于每次只能爬 1 个或 2 个台阶,因此爬到第
i
个楼梯的方式有两种:从第i-1
个楼梯爬一步,或者从第i-2
个楼梯爬两步。因此,状态转移方程为dp[i] = dp[i-1] + dp[i-2]
。 - 初始化: 初始状态为
dp[0] = 1
(起点),dp[1] = 1
。 - 递推计算: 从
dp[2]
开始逐步计算,直到dp[n]
,其中n
为楼梯的总数。 - 计算结果: 返回
dp[n]
,即为爬到楼梯顶部的不同方式数
3、解题代码
java
public int climbStairs(int n) {
/**
确定最优子结构dp[i]=dp[i-1]+dp[i-2]
*/
if (n <= 2) {
return n;
}
int[] dp = new int[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];
}
C++
int climbStairs(int n) {
if(n <= 2){
return n;
}
// int dp[n+1]; //静态数组
int *dp = new int[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];
}
C
int climbStairs(int n) {
int dp[n+2];
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
for(int i = 3;i <= n; i++){
dp[i] = dp[i-2]+dp[i-1];
}
return dp[n];
}
go
func climbStairs(n int) int {
// var dp [n+2]int //数组不行n+2需要为常量应该用切片解决
dp := make([]int, n+2)
dp[0] = 0;
dp[1] = 1;
dp[2] = 2;
var i int;
for i = 3;i <= n;i++{
dp[i] = dp[i-2] + dp[i-1];
}
return dp[n];
}
python3
class Solution:
def climbStairs(self, n: int) -> int:
dp = [0] * (n + 2)
dp[0] = 0
dp[1] = 1
dp[2] = 2
for i in range(3, n + 1):
dp[i] = dp[i - 2] + dp[i - 1]
return dp[n]