初始动态规划—爬楼梯问题

  最近工作比较单调,整体都在学javaweb crud,十分boring。然后买了一本算法导论开始死啃,刚开始看起来真的十分痛苦,真的是大学的债欠的实在是太多了。

  下面就开始直入主题开始记录近期看的第一个知识点动态规划。提起动态规划就不得不提几个动态规划的金典问题爬楼梯、国王金矿、背包问题。今天就自习研究最简单的爬楼梯问题。

列子 问:有一个高度为10级台阶的楼梯,从下往上走,每一次向上跨一个台阶只能是一个台阶或者两个台阶,要求用程序求出来一共有多少种算法?
思考:如果每次都跨一个台阶 则为 1+1+1+1+1+1+1+1+1+1这种方式 、如果每次都跨两个台阶则为2+2+2+2+2+2......很多很多种,最简单暴力的算法就是写个多种循环递归调用输出所有的可行的方法,但是这种方法时效率最低的时间复杂度成指数形式递增。现在我们就开始考虑用动态规划的思路来思考这个问题,动态规划的思路就是将问题拆分、分治。首先将问题先考虑爬楼梯的问题执行到最后一步了,只差一步就可以结束这个请款下的问题,在这个时候只有两种可能了一、从第9阶楼梯跨一步到达10阶和从第8阶一次性跨两个台阶到达10阶。假设到达第9阶台阶的方法为a种,到达第8阶的方法为b种 则到达第10阶的方法则为a+b,ok这个时候我们简写 到10阶台阶的方法为F(10),则F(10) = F(9)+F(8),然后同理继续拆分F(9)=F(8)+F(7),F(8)=F(7)+F(6),拆分到最后当台阶只剩下1阶和二阶的时候很容易得到一个常量 F(1)=1,F(2)=2,由此可得一个公式:

F(n) = F(n-1)+F(n-2) (n>=3)

这个时候我们就得到了用到了动态规划的的概念 F(9)和F(8)是F(10)的最优子结构,F(1)=1,F(2)=2就是动态规划所谓的问题的边界,而上面所得到的公式就是状态转移方程

好了到现在为止 已近理清了我们的思路现在就要开始考虑如何解问题了,代码采用java编写

解法一 :递归

 public int getClimblingWays(int n){
        if ( n<1 ) return 0;
        if (n == 1)return 1;
        if (n == 2)return 2;
        return getClimblingWays(n-1)+getClimblingWays(n-2);
    }

当然这个方法可以解决这个问题但是我们也要考虑 这个是不是运行了是很重复的计算呢?如丑图所示

这个算法的时间复杂度是一个是一个二叉树,每一个节点都去过去进行计算即使已经计算过了 ,我们可不可以做个缓存记住已近计算好的结果呢?这里我们就引出了第二种方法

解法二:备忘录算法

public int getClimblingWaysWithCache(int n, Map<Integer,Integer> map){
        if ( n<1 ) return 0;
        if (n == 1)return 1;
        if (n == 2)return 2;
        if (map.containsKey(n)){
            return map.get(n);
        }else{
            int val =  getClimblingWaysWithCache(n-1,map)+getClimblingWaysWithCache(n-2,map);
            map.put(n,val);
            return val;
        }
    }

这种算法大大减少时间复杂度,其时间复杂发度和空间复杂度都为O(n)

到这里为止我们并未结束 我们要开始转为一下思维我们不用自顶向下的方法转化为自底向上的方法

如图所示

在台阶大于3以后 每一个台阶的走法数之和前两个台阶数有关所有我们在可以优化一种新的方法并不不需要记住每一个子集的解,只需要记住前面两个方法的解就好,因此我们引入了第三种方法

解法三:动态规划解法

 public int getClimblingWays3(int n ){
        if ( n<1 ) return 0;
        if (n == 1)return 1;
        if (n == 2)return 2;
        int a = 1;
        int b = 2;
        int temp =0;
        for(int i = 3;i <= n ;i++){
            temp = b + a;
            a = b;
            b = temp;
        }
        return temp;
    }

程序从i=3开始到i=n结束 即只有F(n)n>=3的时候才开始进入循环。

好了到此为止最简单的动态规划问题就全部梳理好了,第一章 学习笔记完成!!,如有错误请指出谢谢!!

转载于:https://my.oschina.net/u/3663022/blog/3065750

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值