动态规划 (一)

爬楼梯问题

问题描述
现在总共有10层台阶,一只青蛙一次只能跳一阶或两阶。问总共有多少种跳法?

  分析一波: 青蛙即将一步到达第10阶前只有两种情况,即:1.从第9阶一阶跳上去;2.从第8阶两阶跳上去。如果用 F(n)表示青蛙跳到第n阶所需要的步数,则有:

F(1) = 1 , 当 n = 1 时
F(2) = 2 , 当 n = 2 时
F(n) = F(n - 1) + F(n - 2),  当 n > 2 时

所以, 二话不说先来一发递归:

 public static int numsOfStairs(int n) {
        if (n == 1) {
            return 1;
        } else if (n == 2) {
            return 2;
        } else if (n > 2) {
            return numsOfStairs(n - 1) + numsOfStairs(n - 2);
        } else {
            return 0;
        }
    }

我将初始层数设置为40,总共耗时328毫秒。如果设置为100层...反正我没等我电脑把结果跑完...执行结果如下:


  都说递归慢...递归慢,递归为何慢?为啥还要使用递归呢?首先,为什么要是用递归,这很容易去解释,因为它语句简洁、逻辑表达清晰,写出来更能让人去理解,一目了然。那为什么执行地慢?是因为如果递归层数比较深,需要增加额外的堆栈去处理,这样很容易造成 堆栈溢出!!对于递归的每一层,都需要堆栈去存储调用参数和中间变量,所以会增加很多额外的系统开销。

  那有没有办法既能使代码简洁,又能让效率提升呢? 嗯确实是有的,可以采取一种叫做尾递归的方法。怎么去理解尾递归呢?我这里对其概念不做过多介绍,一句话总结什么是尾递归: 将当前计算结果作为参数传入下一层

改用尾递归的代码如下:

/**
     * 
     * @param n
     * @param init1 初始值1
     * @param init2 初始值2
     * @return
     */
    public static int numsOfStairs(int n, int init1, int init2) {
        if (n == 1) {
            return init1;
        } else if (n > 1) {
            return numsOfStairs(n - 1, init2, init1 + init2);
        } else {
            return 0;
        }
    }

再贴上初始值设为40时的测试结果:

  执行速度是不是快了不少?正常的递归需要一层层向下进行递归,然后再向上返回结果。而尾递归只需要向下进行递归,每一层递归时都进行计算,最后再返回一次结果。 除此之外,尾递归以牺牲两个额外空间的方式,来减少了中间变量的存储和返回。这样一来, 不仅效率大大提升,同时也避免了内存溢出。

  那么,接下来就进入正题,引入动态规划算法。使用动态规划算法,可以让每个状态都只计算一次,将结果保存下来进行下一次的计算,同时无需堆栈来保存递归现场。

动态规划算法

  动态规划算法是通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推或者分治的方式去解决。
  动态规划算法的基本思想与分治法类似,也是将待求解的问题分解为若干个子问题(阶段),按顺序求解子阶段,前一子问题的解,为后一子问题的求解提供了有用的信息。在求解任一子问题时,列出各种可能的局部解,通过决策保留那些有可能达到最优的局部解,丢弃其他局部解。依次解决各子问题,最后一个子问题就是初始问题的解。
  由于动态规划解决的问题多数有重叠子问题这个特点,为减少重复计算,对每一个子问题只解一次,将其不同阶段的不同状态保存在一个二维数组中。(百度百科)

  因为每一次都有F(n) = F(n-1)+ F(n-2),因此我们需要用两个临时变量来存储中间结果。同样是爬楼梯问题,使用动态规划后的方案如下:

public static int numsOfStairs(int n) {
        int fn1 = 1, fn2 = 2; // 分别存储 f(n - 1) 和 f(n - 2)
        if (n < 3) {
            return n;
        } else if (n >= 3) {
            int sum = 0;
            for (int i = 3; i <= n; i++) {
                sum = fn1 + fn2;
                fn1 = fn2;
                fn2 = sum;
            }
            return sum;
        } else {
            return 0;
        }
    }
动态规划算法的适用条件:
  1. 最优化原理(最优子结构性质): 一个最优策略的子策略是最优的。一个问题满足最优化原理又称其具有最优子结构性质。
  2. 无后效性: 各阶段的状态都是对过去历史的总结,而只有现阶段状态能影响未来的决策,其他之前的状态都无法影响未来的决策。
  3. 子问题的重叠性: 动态规划将原来具有指数级时间复杂度的搜索算法改进成了具有多项式时间复杂度的算法。其中的关键在于解决冗余,这是动态规划算法的根本目的。动态规划实质上是一种以空间换时间的技术,它在实现的过程中,不得不存储产生过程中的各种状态,所以它的空间复杂度要大于其它的算法。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容