• 【LeetCode & 剑指offer刷题】动态规划与贪婪法题1:70 Climbing Stairs


    【LeetCode & 剑指offer 刷题笔记】目录(持续更新中...)

    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: There are two ways to climb to the top.
    1. 1 step + 1 step
    2. 2 steps
    Example 2:
    Input: 3
    Output: 3
    Explanation: There are three ways to climb to the top.
    1. 1 step + 1 step + 1 step
    2. 1 step + 2 steps
    3. 2 steps + 1 step
     
    //问题:爬楼梯(每次只能爬1步或者2步)
    //分析:具有最优子结构和重叠子问题的两点特性,可以用动态规划方法
    //暴力法:递归分解climbStairs(i,n)=(i+1,n)+climbStairs(i+2,n),由于存在很多重复子问题,效率很低,时间复杂度为O(2^n)(递归二叉树结点数)
    /*
    //方法一:带备忘的自顶向下法(O(n),O(n))
    //分解问题:climbStairs(i,n)=(i+1,n)+climbStairs(i+2,n),i为当前的步子,n为目标的步子
    class Solution
    {
    public:
        int climbStairs(int n)
        {
            vector<int> memo(n);
            return climb_stairs(0, n, memo); //递归
        }
        int climb_stairs(int i, int n, vector<int>& memo)
        {
            if(i>n) return 0; //后面分解的时候有i+1和i+2,故有可能出现i>n的情况
            if(i==n) return 1; //初始值
            if(memo[i] > 0) return memo[i];//已经计算的不必重新计算
            memo[i] = climb_stairs(i+1, n, memo) + climb_stairs(i+2, n, memo);//每一次只能爬一步或两步
            return memo[i];
        }
    };*/
    //方法二:自底向上法(O(n),O(n))
    //通项公式:可以从坐标(i-1)到坐标i,也可以从坐标(i-2)到坐标i,
    //故有dp[i]=dp[i−1]+dp[i−2],dp[i]表示到坐标i的走法,所以可以从按问题规模从小到大计算,这样就不会计算重复问题了 (可以写出递推公式,自上而下分析,自下而上解决)
    //思路:考虑到坐标n,有两种情况,在n-1级台阶上往上跳1级,在n-2级台阶上往上跳2级,故得an = an-1 + an-2,可以推广到其他位置
    class Solution
    {
    public:
        int climbStairs(int n
        {
            if(n <= 0) return 0;
            if(n == 1) return 1;//因为通项公式中最少须有两个初始值
     
            vector<int> dp(n+1); //初始化为0
            dp[0] = 1; dp[1] = 1;
            for(int i = 2; i<=n; i++) dp[i] = dp[i -1] + dp[i-2]; //假设dp[0]=1,则从dp[2]开始满足通项公式
            return dp[n];
           
        }
    };
    //方法三:斐波那契数列(O(n),O(1)) 计算时只保存三个数,故可节省空间(方法二也可以做此优化)
    //方法四:Binets Method(O(logn),O(1)) [[Fn+1 Fn], [Fn Fn-1]] = [[1 1], [1 0]]^n
     
    延伸1:(变态跳台阶)
        如果这个青蛙可以跳1级、2级...n级,则跳上n级台阶有多少种跳法
    思路:跳到n级台阶,an = an-1 + an-2 +....a1 +a0 (a0 = 1,表示从起点一次性跳n级,a1 =1, a2 =2),由数学归纳法可以证明an = 2^(n-1)
     
    延伸2:矩形覆盖 
        我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
     
    /*
    问题:矩形覆盖
    方法:动态规划
    f(n)表示2*n的矩形的覆盖方法
    f(n)可以是2*(n-1)的矩形加一个竖着放的2*1的矩形或2*(n-2)的矩形加2横着放的,
    故递推公式为:f(n)=f(n-1)+f(n-2)
    另外,f(1)=1,f(2)=2,为方便起见,假设f(0) = 1
    */
    class Solution
    {
    public:
        int rectCover(int n)
        {
            if(n <= 0) return 0;
            if(n == 1) return 1;
           
            vector<int> dp(n+1);
            dp[0] = dp[1] = 1;
            for(int i = 2; i<=n; i++)
                dp[i] = dp[i-1] + dp[i-2];
           
            return dp[n];
        }
    };
     
  • 相关阅读:
    继承
    对象与类
    反射
    I/O流
    字符串
    Map的entrySet()方法
    接口与内部类
    Git Usage Summary
    HTML(5)
    毕业设计:下载
  • 原文地址:https://www.cnblogs.com/wikiwen/p/10225978.html
Copyright © 2020-2023  润新知