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过大时,时间超时的提示,这个时候我们就要考虑时间复杂度了。

预备知识:递归和动态规划和分治法都有什么关系?

  1. 动态规划实现:时间和空间复杂度都是最大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. 分治策略用于解决原问题与子问题结构相似的问题,对于各子问题相互独立的情况,一般用递归实现;
  2. 动态规划用于解决子问题有重复求解的情况,既可以用递归实现,也可以用迭代实现;
  3. 贪心算法用于解决具有贪心选择性质的一类问题,既可以用递归实现,也可以用迭代实现,因为很多递归贪心算法都是尾递归,很容易改成迭代贪心算法;
  4. 递归是实现手段,分治策略是解决问题的思想,动态规划很多时候会使用记录子问题运算结果的递归实现。

参考资料: 
1.http://1661518.blog.51cto.com/1651518/1396943 
2.《算法导论》第三版

3.http://blog.csdn.net/tyhj_sf/article/details/53969072

时间: 2024-10-12 20:53:48

70. Climbing Stairs【leetcode】递归,动态规划,java,算法的相关文章

leetCode 70. Climbing Stairs | 动态规划

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? 思考: top steps 1 1 2 2 3 3 4 5 5 8 6 13 ... ... 从上面的分析可以看出,f(top)

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? 题解: 这道题就是经典的讲解最简单的DP问题的问题.. 假设现在在已经爬上来了,你之前那一步是怎么爬的,只有两种选择,1步上来的,或者2步上来的.顺藤摸瓜.写好

刷题70. Climbing Stairs

一.题目说明 题目70. Climbing Stairs,爬台阶(楼梯),一次可以爬1.2个台阶,n层的台阶有几种爬法.难度是Easy! 二.我的解答 类似的题目做过,问题就变得非常简单.首先用递归方法计算: class Solution{ public: int climbStairs(int n){ if(n==1) return 1; if(n==2) return 2; return climbStairs(n-1) + climbStairs(n-2); } }; 非常不好意思,Tim

377. Combination Sum IV 70. Climbing Stairs

back function (return number) remember the structure class Solution { int res = 0; //List<List<Integer>> resList = new ArrayList<List<Integer>>(); public int combinationSum4(int[] nums, int target) { Arrays.sort(nums); return back(

leetCode 70.Climbing Stairs (爬楼梯) 解题思路和方法

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? 思路:题目也比较简单,类似斐波那契. 代码如下: public class Solution { public int climbSta

LeetCode 70 Climbing Stairs(爬楼梯)(动态规划)(*)

翻译 你正在爬一个楼梯. 它须要n步才干究竟顶部. 每次你能够爬1步或者2两步. 那么你有多少种不同的方法爬到顶部呢? 原文 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? 分析 动态规划基础题,首先设置3个变量用于

70.Climbing Stairs(法1递归穷举法2动态规划)

You are climbing a stair case. It takes n steps to reachto the top. Each time you can either climb 1 or 2 steps. In how many distinct ways canyou climb to the top? HideTags Dynamic Programming #pragma once #include<iostream> using namespace std; //法

leetcode 70 Climbing Stairs ----- 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? 还是简单的动态规划问题,很明显可以发现. dp[i] = dp[i-2]+dp[i-1] public class Solution { public int clim

动态规划系列 Leetcode 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. Example 1: Input: 2 Output: 2 Explanation: