70. Climbing Stairs【leetcode】递归,动态规划,java,算法
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.
题目分析:每次只能走1或2步,问n步的话有多少中走法????
可以用动态规划和递归解决,提交代码过程中可能会出现n过大时,时间超时的提示,这个时候我们就要考虑时间复杂度了。
预备知识:递归和动态规划和分治法都有什么关系?
- 动态规划实现:时间和空间复杂度都是最大O(n),代码和运行时间如下图
public class Solution {
public int climbStairs(int n) {
if (n == 1) {
return 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];
}
}
Fibonacci Number算法 时间为O(n)空间为O(1)
public class Solution {
public int climbStairs(int n) {
if(n==1){
return 1;
}
int first=1;
int second=2;
for(int i=3;i<=n;i++){
//f(3)=f(2)+f(1);
//f(4)=(f3)+f(2); int third =0;
third=first+second;
first=second;
second =third;
}
return second;
} }
这里给出运行时间
递归法实现()
public class Solution {
public int climbStairs(int n) {
int mem[] =new int[n+1];
return climb(0,n,mem);
}
public int climb(int i,int n,int mem []){ if(i>n){
return 0;
}
if(i==n){
return 1;
}
if(mem[i]>0){
return mem[i];
}
mem[i]=climb(i+1,n,mem)+climb(i+2,n,mem);
return mem[i];
}
}
1、分治策略(Divide and Conquer)
将原问题分解为若干个规模较小但类似于原问题的子问题(Divide),递归的求解这些子问题(Conquer),然后再合并这些子问题的解来建立原问题的解。因为在求解大问题时,需要递归的求小问题,因此一般用递归的方法实现,即自顶向下。
2、动态规划(Dynamic Programming)
动态规划其实和分治策略是类似的,也是将一个原问题分解为若干个规模较小的子问题,递归的求解这些子问题,然后合并子问题的解得到原问题的解。区别在于这些子问题会有重叠,一个子问题在求解后,可能会再次求解,于是我们想到将这些子问题的解存储起来,当下次再次求解这个子问题时,直接拿过来就是。其实就是说,动态规划所解决的问题是分治策略所解决问题的一个子集,只是这个子集更适合用动态规划来解决从而得到更小的运行时间。即用动态规划能解决的问题分治策略肯定能解决,只是运行时间长了。因此,分治策略一般用来解决子问题相互对立的问题,称为标准分治,而动态规划用来解决子问题重叠的问题。
动态规划一般由两种方法来实现,一种为自顶向下的备忘录方式,用递归实现,一种为自底向上的方式,用迭代实现。
3、贪心算法(Greedy Algorithm)
贪心算法在每一步都做出最优的选择,希望这样的选择能导致全局最优解。对,只是寄希望,因此贪心算法并不保证得到最优解,但是它对很多问题确实可以得到最优解,而且运行时间更短。由此可见,贪心算法是带有启发性质的算法。那什么时候可以用贪心算法呢?当该问题具有贪心选择性质的时候,我们就可以用贪心算法来解决该问题。
贪心选择性质:我们可以通过做出局部最优(贪心)来构造全局最优。只要我们能够证明该问题具有贪心选择性质,就可以用贪心算法对其求解。比如对于0-1背包问题,我们用贪心算法可能得不到最优解(当然,也可能会得到最优解),但对于部分背包问题,则可以得到最优解,贪心算法可以作为0-1背包问题的一个近似算法。
动态规划与递归的比较
就性能而言,我用递归和动态规划实现了斐波纳契数列计算,递归如果超过40的时候就已经需要很长时间了,40次大概需要1秒左右,但是用动态规划要一亿次,才需要4秒,这个相差的可不是几个数量级的问题。事实上,递归实现的斐波那契数列计算时间复杂度为O(2ⁿ),动态规划实现时间复杂度为O(n)所以,在以后的开发中,尽量避免使用递归。
就具体实现上而言,动态规划比普通递归仅仅是多了一步保存子问题计算结果的操作。
例如,斐波那契数列的递归实现如下:
int F(int i)
{
if(i < 1) return 0;
if(i == 1) return 1;
return F(i-1) + F(i - 2);
}
- 而用动态规划算法实现是这样:
int F(int i)
{
if(knownF[i] != unknown){
return knownF[i];
}
if(i == 0) t = 0;
if(i == 1) t = 1;
if(i > 1) t = F(i - 1) + F(i - 2);
return knownF[i] = t;
}
4、总结
- 分治策略用于解决原问题与子问题结构相似的问题,对于各子问题相互独立的情况,一般用递归实现;
- 动态规划用于解决子问题有重复求解的情况,既可以用递归实现,也可以用迭代实现;
- 贪心算法用于解决具有贪心选择性质的一类问题,既可以用递归实现,也可以用迭代实现,因为很多递归贪心算法都是尾递归,很容易改成迭代贪心算法;
- 递归是实现手段,分治策略是解决问题的思想,动态规划很多时候会使用记录子问题运算结果的递归实现。
参考资料:
1.http://1661518.blog.51cto.com/1651518/1396943
2.《算法导论》第三版
3.http://blog.csdn.net/tyhj_sf/article/details/53969072
70. Climbing Stairs【leetcode】递归,动态规划,java,算法的更多相关文章
- 【LeetCode】70. Climbing Stairs 解题报告(Java & Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目大意 题目大意 解题方法 递归 记忆化搜索 动态规划 空间压缩DP 日期 [L ...
- Leetcode之70. Climbing Stairs Easy
Leetcode 70 Climbing Stairs Easy https://leetcode.com/problems/climbing-stairs/ You are climbing a s ...
- Leetcode#70. Climbing Stairs(爬楼梯)
题目描述 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数. 示例 1: 输入: 2 输出: 2 解 ...
- LN : leetcode 70 Climbing Stairs
lc 70 Climbing Stairs 70 Climbing Stairs You are climbing a stair case. It takes n steps to reach to ...
- 42. leetcode 70. Climbing Stairs
70. Climbing Stairs You are climbing a stair case. It takes n steps to reach to the top. Each time y ...
- LeetCode练题——70. Climbing Stairs
1.题目 70. Climbing Stairs——Easy You are climbing a stair case. It takes n steps to reach to the top. ...
- Climbing Stairs - LeetCode
目录 题目链接 注意点 解法 小结 题目链接 Climbing Stairs - LeetCode 注意点 注意边界条件 解法 解法一:这道题是一题非常经典的DP题(拥有非常明显的重叠子结构).爬到n ...
- 刷题70. Climbing Stairs
一.题目说明 题目70. Climbing Stairs,爬台阶(楼梯),一次可以爬1.2个台阶,n层的台阶有几种爬法.难度是Easy! 二.我的解答 类似的题目做过,问题就变得非常简单.首先用递归方 ...
- Min Cost Climbing Stairs - LeetCode
目录 题目链接 注意点 解法 小结 题目链接 Min Cost Climbing Stairs - LeetCode 注意点 注意边界条件 解法 解法一:这道题也是一道dp题.dp[i]表示爬到第i层 ...
- 377. Combination Sum IV 70. Climbing Stairs
back function (return number) remember the structure class Solution { int res = 0; //List<List< ...
随机推荐
- Kafka 源代码分析之LogSegment
这里分析kafka LogSegment源代码 通过一步步分析LogManager,Log源代码之后就会发现,最终的log操作都在LogSegment上实现.LogSegment负责分片的读写恢复刷新 ...
- 3.MQTT paho
一.概述 遥测传输 (MQTT) 是轻量级基于代理的发布/订阅的消息传输协议,设计思想是开放.简单.轻量.易于实现.这些特点使它适用于受限环境.例如,但不仅限于此: 网络代价昂贵,带宽低.不可靠. 在 ...
- 2.如何搭建MQTT环境
1.源码下载https://github.com/andsel/moquette 注意下载2016.2版本2.idea下载http://confluence.jetbrains.com/display ...
- 利用CSS3新特性实现完全兼容的自定义滚动条。
背景:最近项目里面因为统一页面风格,用到了自定义滚动条,在完成之前的那个滚动条的时候,与网上各个滚动条插件实现的方法类似,相当于造了轮子,通过css3的 网上看到的滚动条插件多数是通过监听内容的滚动事 ...
- VMware Mac OS中无法找到适应的分辨率的解决办法
使用VMware安装的Mac OS中,有时在显示器的分辨率中的选择项里面,没有对应显示的分辨率可供选择的时候(无法自适应),可以在虚拟机设置里,显示器中修改强制分辨率.修改过后重启虚拟机,就可以有对应 ...
- iOS开发Safari调试WebView页面
App混合开发现已是常态,不过作为app端开发人员,对H5页面的使用,可不能简单的局限于使用,一些简单的调试方法还是有必要了解的. 关于如何在使用webview过程中,如何对web内对内容进行调试,这 ...
- 一级缓存二级缓存(hibernate)
缓存是介于应用程序和物理数据源之间,其作用是为了降低应用程序对物理数据源访问的频次,从而提高了应用的运行性能.缓存内的数据是对物理数据源中的数据的复制,应用程序在运行时从缓存读写数据,在特定的时刻或事 ...
- 搭建nexus私服(maven)
这里提供nexus的直接下载页面的链接: https://www.sonatype.com/download-oss-sonatype maven获取依赖jar包是从中央仓库获取,但很莫名的出现jar ...
- H3CNE实验:Comware基本命令操作
第1步:Comware命令视图及切换操作 <H3C>system-view System View: return to User View with Ctrl+Z. [H3C]quit ...
- 为Dynamics 365写一个简单程序实现解决方案一键迁移
关注本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复258或者20170627可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyong. ...