明明白白之动态规划

上一篇:网络原理-TCP-IP

1、动态规划定义:
动态规划是分治思想的延伸,和递归类似,却又不是递归。在将大问题化解为小问题的分治过程中,保存对这些小问题已经处理好的结果,并供后面处理更大规模的问题时直接使用这些结果。

2、 动态规划具备以下三个特点:
1) 把原来的问题分解成了几个相似的子问题
2) 所有的子问题都只需要解决一次
3) 储存子问题的解

3、 动态规划的本质是对问题状态的定义和状态转移方程的定义(状态以及状态之间的递推关系)动态规划问题一般从以下四个角度考虑:
1) 状态定义
2) 状态间的转移方程定义
3) 状态的初始化
4) 返回结果
把握以上四个角度,问题就迎刃而解了。

状态定义的要求:定义的状态一定要形成递推关系(一步一步走)

4、 适用场景:最大值/最小值,可不可行,存不存在,是不是,方案个数。

5、举个栗子:
在这里插入图片描述
例题Ⅰ:斐波那契数列

题目要求:输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。n<=39

大家一看到这道题,脑海里肯定会想到:斐波那契?简单啊,递归不就行了。非也非也~

首先来看递归的做法:

public class Solution {
    public int Fibonacci(int n) {
        if(n == 0) return 0;
        if(n < 3) return 1;
        else {
            return Fibonacci(n - 1) + Fibonacci(n - 2);
        }
    }
}

f(n) = f(n-1) + f(n-2),确实第一眼看就是递归啊,简直完美的递归环境,这样想着,两三行代码就搞定了。
但其实这样写,n稍微大一点很容易产生Stack Overflow。为什么会溢出呢?因为这其中存在着大量的重复计算。以n=4为例,因为代码并没有记录Fibonacci(1)和Fibonacci(0)的结果,对于程序来说它每次递归都是未知的,因此光是n=4时f(1)就重复计算了3次之多。所以就很容易产生Stack Overflow。

用动态规划来看:

初始状态:F[0] = 0 ; F[1] = F[2] = 1 ;
转移方程:F[i] = F[i - 1] + F[i - 2];
返回值:F[n];

public class Solution {
        public int Fibonacci(int n) {
            if(n == 0) return 0;
            if(n < 3) return 1;
            else {
                int[] f = new int[n + 1];
                f[0] = 0;
                f[1] = f[2] = 1;
                for(int i = 3;i <= n; ++i){
                    f[i] = f[i - 1] + f[i - 2];
                }
                return f[n];
            }
        }
    }

这样就相当于定义了一个数组来存放F[n],当进行下一步操作时,可以直接调用数组里F[n]的数值,省去了大量的重复计算。

例题Ⅱ:变态跳台阶

题目要求:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

推导过程:
在这里插入图片描述
分析以后代码就很好写了:

public class Solution {
    public int JumpFloorII(int target) {
        if (target <= 0) {
            return -1;
        } else if (target == 1) {
            return 1;
        } else {
            return 2 * JumpFloorII(target - 1);
        }
    }
}

以上两道题帮助大家理解动态规划,如果着实搞不清楚动态规划的话,推荐一个动态规划的短漫画来加强理解:

什么是动态规划?
在这里插入图片描述
看完之后你肯定会觉得任督二脉已打通,动态规划不过如此!

下一篇:明明白白之搜索算法


在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值