这篇文章参考了以下博客或者公众号:
1、动态规划图解 作者:NFGC(Leetcode题解)
之前 我写了一篇博客:动态规划 第0讲:基础入门课
对动态规划算法进行了大致的讲解。
接下来两周,我们将会一步一步、由浅到深来分析各个类型的题目。
首先,当然是最简单的一维动态规划算法了。
这篇文章包含了LeetCode的以下题目:
一、70. 爬楼梯 (难易程度:easy)
二、91. 解码方法 (难易程度:medium)
三、96. 不同的二叉搜索树 (难易程度:medium)
四、53. 最大子序和 (难易程度:easy)
五、152. 乘积最大子数组 (难易程度:medium)
六、198.打家劫舍(难易程度:easy)
一、70. 爬楼梯 (难易程度:easy)
原题链接:https://leetcode-cn.com/problems/climbing-stairs/
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?
注意:给定 n 是一个正整数。
示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
one. 1 阶 + 1 阶
two. 2 阶
示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
one. 1 阶 + 1 阶 + 1 阶
two. 1 阶 + 2 阶
three. 2 阶 + 1 阶
解题思路:
这是十分经典的斐波那契数列题。定义一个数组 dp,dp[i] 表示走到第 i 阶的方法数。因为我们每次可以走一步或者两步,所以第 i 阶可以从第 i-1 或 i-2 阶到达。换句话说,走到第 i 阶的方法数即为走到第 i-1 阶的方法数加上走到第 i-2 阶的方法数。这样我们就得到了状态转移方程dp[i] = dp[i-1] + dp[i-2]。注意边界条件的处理。
首先,很自然地想到用**动态规划(递归)**去求解:
看看代码:
class Solution {
public:
int climbStairs(int n) {
int ans;
if(n<=2) return n;
return climbStairs(n-1)+climbStairs(n-2); //递归
}
};
但是呢,超时了:
好,我们把递归改成递推试试看:
class Solution {
public:
int climbStairs(int n) {
int ans;
if(n<=2) return n;
vector<int>dp(n+1, 0);
dp[1]=1; dp[2]=2;
for(int i=3; i<=n; i++) //递推
dp[i]=dp[i-1]+dp[i-2];
return dp[n];
}
};
好,改成递推之后就通过了!
二、91. 解码方法 (难易程度:medium)
原题链接: https://leetcode-cn.com/problems/decode-ways/
一条包含字母 A-Z 的消息通过以下方式进行了编码:
‘A’ -> 1
‘B’ -> 2
…
‘Z’ -> 26
给定一个只包含数字的非空字符串,请计算解码方法的总数。