目录

  • 斐波那契数列的启发
  • 第一个例子
  • 第二个例子
  • 参考资料

斐波那契数列的启发

在讨论动态规划之前,我们先看一个熟悉的例子——斐波那契数列(Fibonacci sequence):

如果我想求f(3)f(3)f(3),那我只要知道f(1)f(1)f(1)和f(2)f(2)f(2)就可以了,同理,如果想知道f(4)f(4)f(4),那我需要知道f(2)f(2)f(2)和f(3)f(3)f(3)。以此类推,如果我想知道f(n)f(n)f(n),那么只要已知f(1)...f(n−1)f(1)...f(n-1)f(1)...f(n−1)即可。对于像具有像斐波那契数列这样递推关系的问题,都可以用这种方法求解。虽然这样看上去有点笨,却是一个用空间换时间的高效方法,因为这样时间复杂度就能降到O(n)O(n)O(n),而用递归的方法时间复杂度可能达到O(2n)O(2^n)O(2n)。下面我们看一个例子:

第一个例子

对于数组[a1a2...an][a_1\ a_2 \ ... \ a_n][a1​ a2​ ... an​],求出不相邻元素的最大和。

将问题具体化,我们求[1 2 4 1 7 8 3](如下图上列为下标号,下列为元素)的不相邻元素的最大和。从后往前推,arr[6]=3,它的最近不相邻元素的是arr[4]=7。这时有两种可能,一种选arr[6],则sum=arr[4]+arr[6],另一种是不选arr[6],直接看arr[5]和它的不相邻元素。

为了方便描述,我们用函数rec_opt()来描述递归选择的过程,如下图所示。

明显这是一个递归关系,递归的出口是rec_opt(0)=1,rec_opt(1)=max(arr[0],arr[1])。这样我们可以写出递归代码:

static int rec_opt(int[] arr,int i){//i表示开始递归的位置,本例从arr的最后一个元素开始递归if(i==0)return arr[0];if (i==1)return Math.max(arr[1],arr[0]); //选1则返回arr[1],不选1则返回arr[0]else return Math.max(rec_opt(arr, i-1),rec_opt(arr, i-2)+arr[i]);}

但这样的方法时间复杂度为O(2n)O(2^n)O(2n),且占用内存大。我们观察递归算法的二叉树形式,会发现上层的rec_opt都是用rec_opt(0)、rec_opt(1)累积出来的。如果我们创建一个数组,记录从rec_opt(0)、rec_opt(1)到rec_opt(i)的所有值,就不用再重复调用rec_opt了。

于是我们可以得出非递归的算法:

static int dp_opt(int[] arr){int []temp= new int[arr.length];temp[0]=arr[0];temp[1]=arr[1];for (int j=2;j<arr.length;j++) {temp[j]=Math.max(temp[j-2]+arr[j],temp[j-1]);}return temp[arr.length-1];}

我们再看另外一个例子:

第二个例子

判断一个序列是否存在和等于s的子列。


设序列为[3,34,4,12,5,23],s=9。还是按照之前的思路,从最后一个元素开始向前遍历。如23大于9,则跳过,5小于9,则s=s-5=4。当s=0时,说明找到了要找的子列。如果所有都遍历完s还不为0,则没找到。因此我们可以得到如下的递归算法:

static boolean rec_series(int[] arr,int i,int s){if (s==0) {//如果正好没有剩余,则返回truereturn true;}else if (i==0) {//若正好遍历到最后一个,当最后一个就是s时,返回truereturn arr[i]==s;} else if (arr[i]>s) {//如果第i个比s大,只能不选择return rec_series(arr,i-1,s);}else {//上述情况都不存在,可以选择第i个元素,也可以跳到第i-1个元素return rec_series(arr,i-1,s-arr[i]) || rec_series(arr,i-1,s);}}

同样,我们可以借鉴前面的思想,列出如下图所示的二维表,记录rec_series(arr,i,s)的结果。其中第一行是循环开始前初始化的内容。由于后面的结果依赖前面,所以i=5,s=9就是最终的结果。

以下为动态规划的算法:

static boolean dp_series(int[] arr,int s){boolean [][]b=new boolean[arr.length][s];for (int i=0;i<s;i++) {//初始化二维表的第一行if(arr[0]==i) {b[0][i]=true;}}for (int i=1;i<arr.length;i++) {//把递归过程变成查表过程for(int j=0;j<s;j++){if(j==arr[i]){b[i][j]=true;}else if(j<arr[i]) {b[i][j]=b[i-1][j];}else {b[i][j]=b[i-1][j-arr[i]-1];}}}return b[arr.length-1][s-1];}

参考资料

动态规划 (第1讲)
动态规划 (第2讲)

【经典算法】动态规划相关推荐

  1. 五大经典算法-动态规划 及其算法应用

    前言 整篇文章分析整个动态规划算法,什么是动态规划,及动态规划算法在字符串匹配中使用.分治法的差别点.动态规划优点: 概念 什么叫做动态规划(dynamic programming),它是运筹学的一个 ...

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

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

  3. 经典算法书籍推荐以及算法书排行【算法四库全书】

    经典算法书籍推荐以及算法书排行[算法四库全书] 作者:霞落满天   https://linuxstyle.blog.csdn.net/    https://blog.csdn.net/21aspne ...

  4. 还在为数学建模的事发愁?带你一起来看看数模竞赛中必备的经典算法

    前言 数学建模比赛是本科生和研究生阶段最重要的比赛之一,包括全国大学生数学建模竞赛(俗称"国赛")和美国大学生数学建模竞赛(俗称"美赛").在这些比赛中取得好成 ...

  5. 程序员必须要掌握的十大经典算法

    算法一:快速排序算法 快速排序是由东尼·霍尔所发展的一种排序算法.在平均状况下,排序 n 个项目要Ο(n log n)次比较.在最坏状况下则需要Ο(n2)次比较,但这种状况并不常见.事实上,快速排序通 ...

  6. 《算法之道》精华 经典算法部分

    <算法之道>精华 经典算法部分 本书作者邹恒明,作者另有一本书<数据结构之弦>,以及<操作系统之哲学原理>都是非常好的书 这本书能够算得上是深入浅出,文笔非常好.作 ...

  7. java架构师进阶之独孤九剑(一)-算法思想与经典算法

    " 这是整个架构师连载系列,分为9大步骤,我们现在还在第一个步骤:程序设计和开发->数据结构与算法. 我们今天讲解重点讲解算法. 算法思想 1 贪心思想 顾名思义,贪心算法总是作出在当 ...

  8. JAVA经典算法大全

    JAVA经典算法大全 from http://java-mans.iteye.com/blog/16457031.河内之塔 2.Algorithm Gossip: 费式数列. 3.巴斯卡三角形 4.A ...

  9. 算法探讨——再议经典算法问题:求最大子序列和、绝对值最大子序列和以及其区间...

    算法探讨--再议经典算法问题:求最大子序列和.绝对值最大子序列和以及其区间 给定任一数字序列,如{-5,4,-20,16,-2,-3},求出其最大子序列和,绝对值最大子序列和以及对应的区间,在这个例子 ...

  10. 【算法特训总结】计算机经典算法的核心思想及独特角度的解读

    计算机经典算法的核心思想及独特角度的解读 在1月1日新年之日开始的"算法特训"(一月一日~二月十日)终于结束了,对于这本<<算法竞赛经典>>,除了第十章(在 ...

最新文章

  1. 罗伯特扫地机器人电池如何取_irobot扫地机器人电池怎么拆 iRobot/艾罗伯特扫地...
  2. 如何从ERP将Material的Batch信息下载到CRM并存储在settype COMM_PR_BATCH里
  3. pytorch 初始化权重
  4. red hat linux FTP配置
  5. windows和linux多进程效率,Windows程序效率 (转)
  6. 平行志愿计算机录取顺序,2020平行志愿的录取顺序你知道吗?
  7. 网络编程之 字节序和深入理解bind()函数
  8. [转]iOS设备唯一标识探讨
  9. 构造器2(Java)
  10. 恢复系统管理员密码的五大奇招
  11. MODIS数据火点提取方法
  12. 致远OA ajaxAction formulaManager 文件上传漏洞
  13. 播放和保存视频,图像倒置纠正到本地文件夹(含ffmpeg ,pyav多线程读取多路网络摄像头)
  14. ppt幻灯片如何与母版背景一块复制到新幻灯片
  15. Linux 3.10内核锁瓶颈描述以及解决-IPv6路由cache的性能缺陷
  16. 失眠怎么办?试试汤臣倍健褪黑素和以下方法!
  17. Android 优化开机启动
  18. 17.继承和派生的基本概念
  19. 最大似然估计(机器学习)
  20. matlabff2函数_罚函数法MATLAB程序.doc

热门文章

  1. 搜狗违禁词屏蔽垄断关键词批量过滤工具
  2. 一个新的App该如何推广
  3. php实现一周课程发布,php中文网一周学会php直接课程开课时间公告
  4. PS怎么做流线光效人物动图效果
  5. 【笔记】高级运动营养学
  6. 盛泰转债上市价格预测
  7. AxTocControl的EnableLayerDragDrop属性与selectItem、getselectitem与hittest
  8. 一个 DAG 工作流引擎的设计实现源代码实例
  9. 初中计算机教师资格证内容,教师资格证考试大纲——《信息技术学科知识与教学能力》(初级中学)...
  10. Adobe Photoshop CC (32/64位) 绿色精简版