LeetCode 70. Climbing Stairs 自顶向下记忆化搜索,自底向上重叠子问题动态规划
2017-06-15 19:31
435 查看
70. Climbing Stairs
You are climbing a stair case. It takes n steps to reach to the top.Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Note: Given n will be a positive integer.
题意
爬楼梯案例。需要n步能到达楼梯的尽头每一个你可以选择爬1阶或者2阶楼梯。有多少种方案可以爬到顶端
给定的n是一个正整数
思路1
类似斐波那契数的解法分析f[i]表示i个台阶有多少种爬的方式
f[1] = 1; f[2] = 2;
f
= f[n-1]+f[n-2]典型的递归结构
求n阶台阶需要知道爬n-1阶和n-2阶台阶,有多少种爬的方式。以此递推,不断向下查找。自顶向下
直到递归结束条件:n==1或n==2时
代码1
//算法复杂度:O(2^n)指数级 class Solution { private: int res; //f(1)=1, f(2) = 2; f(n) = f(n-1)+f(n-2) //统计走第i个楼梯有多少种可能 int calcStairs(int i) { if(i == 1) return 1; if(i == 2) return 2; res = calcStairs(i-1)+calcStairs(i-2); return res; } public: int climbStairs(int n) { //n个台阶,范围是[0...n],总共有n+1个元素 vector<int> count(n+1,-1); //类似于斐波那契数,解法1,自底向上,从子问题开始 res = calcStairs(n); return res; } };
结果当然是超时
思路2
通过观察思路1,发现有大量的重复计算,即重叠的子问题。可以使用记忆化方式,减少进入递归的次数,通过查表的方式,直接获取结果。对于相同的台阶数,只计算一次。这样能极大的加快算法代码2
class Solution { private: vector<int> count; //f(1)=1, f(2) = 2; f(n) = f(n-1)+f(n-2) //直接使用递归超时,未做任何优化 //统计走第i个楼梯有多少种可能 int calcStairs(int i) { if(i == 1) return 1; if(i == 2) return 2; if(count[i] == -1) { count[i] = calcStairs(i-1)+calcStairs(i-2); } return count[i]; } public: int climbStairs(int n) { int res; //n个台阶,范围是[0...n],总共有n+1个元素,来记忆n个台阶可走的可能 count = vector<int>(n+1,-1); //类似于斐波那契数,解法1,自底向上,从子问题开始 res = calcStairs(n); return res; } };
获得了一个AC
思路3
之前的思路都是自顶向下,递归的向下去寻找。通过分析发现,n个台阶可能的走法,实际上可以转换为一个子问题的求解,当子问题得到解,那么将子问题的解合起来,也就是整个问题的解。这样的方法称之为动态规划,自底向上。
代码3
class Solution { public: int climbStairs(int n) { //n个台阶,范围是[0...n],总共有n+1个元素 vector<int> count(n+1,-1); //类似于斐波那契数,解法1,自底向上,从子问题开始 count[1] = 1; count[2] = 2; for(int j=3;j<=n;j++) { count[j] = count[j-1]+count[j-2]; } return count ; } };
这样的代码比起思路1和2简洁了很多。通过求解子问题来达到全局解
总结
动态规划:将原问题拆解成若干子问题,同时保存子问题的答案,使得每个子问题只求解一次,最终获得原问题的答案。相关文章推荐
- 动态规划-重叠子问题
- 动态规划之重叠子问题属性(Overlapping Subproblems Property)
- leetcode 198:动态规划求小偷偷东西问题:
- 动态规划-3.1.2矩阵连乘问题之迭代法(自底向上)
- leetcode-3 Longest Substring Without Repeating Characters经典的动态规划问题
- leetcode 322. Coin Change 类似背包问题 + 很简单的动态规划DP解决
- [LeetCode198 House Robber]数组中的动态规划求最值问题
- 算法之动态规划 之 子问题重叠和最优子结构
- Leetcode 120. Triangle 三角形问题(动态规划经典) 解题报告
- leetcode 213. House Robber II 入室抢劫 抢劫问题 + 一道经典的DP动态规划问题
- leetcode 279. Perfect Squares 类似背包问题 + 很简单的动态规划DP解决
- 动态规划之01背包问题及leetcode实例
- leetcode 174. Dungeon Game 一个逆着推导计算的DP动态规划问题
- 练习题 No.5 背包问题(动态规划-记忆化搜索)
- 动态规划之钢条切割问题自底向上发的实现(算法导论第15章)
- LeetCode 在矩阵中寻找路径类的动态规划问题
- C#实现递归矩阵连乘(动态规划的递归自顶向下,非递归自地向上)
- leetcode 53. Maximum Subarray(DP动态规划问题)
- 0/1背包问题动态规划详解之一
- 01背包问题动态规划详解