动态规划有多重要?

  • 科技公司面试必考算法
  • 根据面试经验,一半失败的面试都与动态规划有关

动态规划题目特点

1、计数题

-有多少种方式走到右下角

-有多少种方法选出k个数使得和是Sum

2、求最大最小值

-从左上角走到右下角路径的最大数字和

-最长上升子序列长度

3、求存在性

-取石子游戏,先手是否必胜

-能不能选出k个数使得和是Sum

动态规划的特点

1、将原问题分解为相似的子问题

2、所有的子问题都只需解一次(即存储解过的问题)

3、使用空间换时间

4、自底向上求解

目录

一、Coin Change题

1、确定状态

最后一步

子问题

2、转移方程

3、初始条件和边界情况

4、计算顺序

5、代码

二、Unique Paths

1、子问题

2、转移方程

3、初始条件和边界情况

初始条件

边界情况

4、计算顺序

5、代码

三、Jump Game

1、确定状态

2、转移方程

3、初始条件和边界情况

初始条件

边界情况

4、计算顺序

5、代码


一、Coin Change题

科大讯飞笔试题

题目:

有三种硬币,分别面值2元、5元和7元,每种硬币都有足够多,现在买一本书需要27元,问如何用最少的硬币组合正好付清,不需要对方找钱?

你是否同意下面的想法?

题目要求用最少的硬币,也就是尽量用大的硬币,最后用一种硬币付清即可;

如:7+7+7=21,21+2+2+2=27;

用了6枚硬币。

但正确答案是:7+5+5+5+5=27,共5枚硬币。

而正确的做法是使用动态规划解,如何使用动态规划?动态规划的组成部分有哪些?

1、确定状态

确定状态即使用一个数组,数组的每个元素f[i]或f[i][j]代表什么。

确定状态需要做两件事:最后一步、子问题。

最后一步

先忽略解题的最优策略是什么,但最优策略肯定是K枚硬币a1...ak加起来等于27;

所以必存在一枚最后的硬币:ak;

去掉这枚硬币,前面的硬币加起来就是27-ak。

由以上说法可以得出两个关键点。

1、不关心前面的k-1枚硬币是如何拼出27-ak的,但是确定前面的硬币拼出了27-ak。

2、拼出的27-ak硬币数一定最少,否则就不是最优策略了。

子问题

所以可以将原问题“最少用多少枚硬币拼出27”转换为子问题“最少用多少枚硬币可以拼出27-ak”。

为了简化,可以设状态f(x)=最少用多少枚硬币拼出x。

现在还不知道最后那枚硬币ak是多少?

ak只可能是2、5或7;

如果ak=2,f(27)=f(27-2)+1        (f表示的是个数,所以加上最后一枚硬币是+1)

如果ak=5,f(27)=f(27-5)+1

如果ak=7,f(27)=f(27-7)+1

需要求最少的硬币数,所以可得出以下公式:

f(27)=min{f(27-2)+1,f(27-5)+1,f(27-7)+1}

看到上面的公式,一定有人问:为什么不用递归?

递归解法的问题:

由图可得:递归解法做了很多重复计算,效率低下。

那么如何避免重复计算的问题?将计算结果保存下来,并改变计算顺序。

2、转移方程

设状态f[x]=最少用多少枚硬币拼出x

对于任意x,有:

现在思考一下,如果要求使用最多的硬币拼呢?

那么可以将方程的min改为max

如果写出了转移方程,那么就成功了一半。

仅仅写出转移方程还是不够,在编写程序前还需做两件事。

3、初始条件和边界情况

在得出方程后衍生两个问题:如果x-2、x-5、x-7小于0怎么办?什么时候停下?

如果不能拼出Y,就定义f[Y]=正无穷,此处的正无穷是尽可能大的数。

初始条件:f[0]=0,因为方程不能得出x=0的正确答案,需要手动定义。

4、计算顺序

从初始后开始计算;

初始条件:f[0]=0;

然后计算f[1]....f[27]

当计算到f[x]时,前面的f[x-2]、f[x-5]、f[x-7]已经得到结果,可以直接使用(这里体现了动态规划的一个特点即动态的存储计算过的数据)。

使用动态规划解此题过程如下:

每一步尝试三种硬币,一共27步。

如果有n种硬币,拼m块硬币

动态规划解此题的时间复杂度:n*m

而递归时间复杂度是指数级别,要>>n*m

5、代码

int a[MAX],m;//a存放硬币种类,M为求解的总硬币数int n;int i,j;int f[m+1];f[0]=0;for(i=1;i<=m;i++){f[i]=MAX;for(j=0;j<n;j++){if(i>=a[j]&&f[i-a[j]]!=MAX){if(f[i-a[j]]+1<f[i])f[i]=f[i-a[j]]+1;}}}if(f[m]==MAX){return -1;}printf("%d",f[m]);
}

二、Unique Paths

题目:

给定m行n列网格,有一个机器人从左上角(0,0)出发,每一步可以向下或向右走一步,问有多少种不同的方式走到右下角?

1、子问题

如果机器人有X种方式从左上角走到(m-2,n-1),有Y种方式从左上角走到(m-1,n-2),则机器人有X+Y种方式走到(m-1,n-1)。

可以由原题“有多少种方式从左上角走到(m-1,n-1)”转化为子问题“机器人有多少种方式从左上角到(m-2,n-1)和(m-1,n-2)”

2、转移方程

对于任意一个格子(i,j),有方程:

3、初始条件和边界情况

初始条件

f[0][[0]=1,因为机器人只有一种方式到左上角

边界情况

i=0或j=0(即第一行和第一列),前一步只能有一个方向过来,使f[0][j]=1,f[i][0]=1。

4、计算顺序

f[0][0]=1

计算第0行:f[0][0]、f[0][1]....f[0][n-1]

....

计算第m-1行:f[m-1][0]、f[m-1][1]......f[m-1][n-1]

答案为:f[m-1][n-1]

为什么要按行计算?

因为对于任意一个格子,如果按行计算,那么它的上边和左边的格子都已经计算过了。

时间复杂度:O(MN)

5、代码

    int n,m;int f[m][n];int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++){if(i==0||j==0)//第一行和第一列是边界情况,因为第一行的格子只能由左方向来,第一列只能从上来 f[i][j]=1;elsef[i][j]=f[i-1][j]+f[i][j-1];}}printf("%d",f[m-1][n-1]);

三、Jump Game

网易笔试题

题目:
有n块石头分别在0,1,.....,n-1位置,有一只青蛙在石头0,想跳到石头n-1,如果青蛙在第i块石头上,它最多可以向右条距离ai,问青蛙能否跳到石头n-1?

例:

输入:a[2,3,1,1,4]

输出:True

输入:a=[3,2,1,0,4]

输出:False

此题可用动态规划也可用其他算法如贪心。

1、确定状态

假设存在一个石头i可以跳到石头n-1,则可将原问题“能不能跳到石头n-1”转换为子问题“能不能跳到石头i”。

设状态f[j]表示能不能跳到石头i。

2、转移方程

思考如何判断是否能跳到石头i?

需要考虑以下步骤:

1、枚举i前面的石头j

2、判断前面的石头能否跳到石头j(如果前面的都跳不到j,那j能跳到i也没用了)

3、如果j有效,则判断j+a[j]>=i,否则跳不到i

3、初始条件和边界情况

初始条件

f[0]=True,因为青蛙一开始就在石头0

边界情况

无边界情况,不会越界。

4、计算顺序

初始化f[0]=True

计算f[1],f[2]....f[n-1]

答案是f[n-1]

时间复杂度:O(N^2)

5、代码

    int a[num];int i,j;bool f[num];f[0]=true;for(i=1;i<num;i++){f[i]=false;for(j=0;j<i;j++){if(f[j]&&j+a[j]>=i){f[i]=true;break;}}}printf("%d",f[num-1]);

【算法】-- LintCode经典算法题理解动态规划相关推荐

  1. 2020腾讯广告算法大赛:赛题理解与解题思路

    写在前面 期待已久的2020腾讯广告算法大赛终于开始了,本届赛题"广告受众基础属性预估".本文将给出解题思路,以及最完备的竞赛资料,助力各位取得优异成绩!!! 报名链接:https ...

  2. 计算机语言算法大全,经典算法大全

    标签: 算法 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时间内获得所要求 ...

  3. java 所有路径算法_经典算法题:二叉树的所有路径

    一.题目 给定一个二叉树,返回所有从根节点到叶子节点的路径. 二.思路 回溯算法 三.实现 public List binaryTreePaths(TreeNode root) { List res ...

  4. java 算法_JAVA经典算法40题

    [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 1.程序分析: 兔子的规律为数列1,1 ...

  5. 汉诺塔算法python_经典算法:汉诺塔

    学编程,学IT,算法也是必不可缺的,这一次给大家带来一个经典的递归算法题,汉诺塔.算是算法的入门小题目之一吧~ 视频教程 什么是汉诺塔? 我这里直接拉来一个图解释一下(挂了请联系我) 就是这么一个东西 ...

  6. 货郎担问题java算法_经典算法(1)---货郎担问题

    一.货郎担问题 货郎担问题属于易于描述但难于解决的著名难题之一,至今世界上还有不少人在研究它.该问题的基本描述是:某售货员要到若干个村庄售货,各村庄之间的路程是已知的,为了提高效率,售货员决定从所在商 ...

  7. k近邻回归算法python_经典算法之K近邻(回归部分)

    1.算法原理 1.分类和回归 分类模型和回归模型本质一样,分类模型是将回归模型的输出离散化. 一般来说,回归问题通常是用来预测一个值,如预测房价.未来的天气情况等等,例如一个产品的实际价格为500元, ...

  8. 计算机大赛算法,计算机经典算法——锦标赛排序算法

    关键词:二叉树 生活中的淘汰锦标赛:在单淘汰的锦标赛中,选手们两两比赛,胜者晋级,败者被淘汰.比如世界乒乓球锦标赛或者大满贯网球赛就是这么进行的. 这样一来,就可以把比赛的赛程和结果对应成一个二叉树. ...

  9. 五大经典算法(贪婪、动态规划、分治、回溯、分支限界法)及其联系和比较

    一.贪心法 贪心算法的含义: 贪心算法(也叫贪婪算法)是指在对问题求解时,总是做出在当前看来是最好的选择.也就是说,不从整体最优上加以考虑,只做出在某种意义上的局部最优解.贪心算法不是对所有问题都能得 ...

最新文章

  1. hdu 4417 Super Mario 划分树+二分
  2. 一个简单的freemark输入输出的案例(一)
  3. Netty实战 IM即时通讯系统(十)实现客户端和服务端收发消息
  4. Spring Cloud的应用程序—上下文服务
  5. Android 解决导入多个module时jar包冲突
  6. View Agent Direct-Connection安装后,连接黑屏
  7. 2017.9.20 cheat 失败总结
  8. 2020 年 9 月程序员平均工资 14469 元,你拖后腿了没?
  9. 关于RIGOL可编程电源连接说明(网口连接)
  10. java分享微博_java_java实现的新浪微博分享代码实例,weibo.java {@link IWeiboShareAPI#handle - phpStudy...
  11. 蝴蝶效应,混沌理论与股市
  12. 内存卡没有Android,安卓内存卡读不出来怎么办
  13. KJ分析法(亲和图)的应用实例及知识分享
  14. NaN是什么?NaN == NaN 的结果是什么?为什么?
  15. AHB总线笔记(一)
  16. 学术新秀采访-陆品燕~How To Get Your SIGGRAPH Paper Rejected
  17. java根据日期判断星座_给定公历日期计算12星座(Java代码实现)
  18. mysql 微信 jsp_SpringMVC+Spring+mybatis+mysql+jsp微信商城系统,有后台管理系统
  19. UVA 12563 Jin Ge Jin Qu hao(多阶段决策问题,DP)
  20. windows10 mysql-8.0.20 重新初始化

热门文章

  1. 雷电模拟器一直android正在启动,雷电模拟器启动失败卡在0-29%怎么解决 加载卡0-29%教程...
  2. 计算机CQ,什么是Cq(Ct)值?
  3. mysql查询已知两列第三列,MySQL查询从两列中查找出现的次数?
  4. C#上位机开发源码基于RS485通讯总线的ModbusRtu协议,支持用户权限管理
  5. 【620】【信息管理基础】【信息政策与信息法律】
  6. Vmware虚拟机设置主机端口映射
  7. 〖全域运营实战白宝书 - 运营角色认知篇⑧〗- 运营人的发展路径
  8. 【SQL Server】10分钟快速安装SQL Server
  9. 图像处理——噪声小记
  10. 开发一套软件的成本费用?这里有八个要点