您当前的位置:首页 > 电脑百科 > 程序开发 > 算法

高效的动态规划算法

时间:2019-08-28 10:51:03  来源:  作者:

选自medium

作者:Meet Zaveri

机器之心编译

参与:曾祥极、张倩

乔治·桑塔亚纳说过,“那些遗忘过去的人注定要重蹈覆辙。”这句话放在问题求解过程中也同样适用。不懂动态规划的人会在解决过的问题上再次浪费时间,懂的人则会事半功倍。那么什么是动态规划?这种算法有何神奇之处?本文作者给出了初步的解答。

假设你正在使用适当的输入数据进行一些计算。你在每个实例中都进行了一些计算,以便得到一些结果。当你提供相同的输入时,你不知道会有相同的输出。这就像你在重新计算之前已经计算好的特定结果一样。

那么问题出在哪里呢?你之前计算某些结果的宝贵时间被浪费掉了。你可以通过保存之前的计算结果去轻易地解决这个问题。比如通过使用恰当的数据结构。举个例子,你可以将输入输出作为键值对映射保存起来。

那些遗忘过去的人注定要重蹈覆辙 ~ 动态规划

 

现在通过分析这个问题,我们可以将新的输入(或者不在数据结构中的输入)与其对应的输出存储下来。或者在字典中查找输入并返回相应的输出结果。这样当你在进行一些计算时,你可以检查数据结构中是否存在该输入,如果数据输入存在的话就可以直接获得结果。我们将与这种方法相关的技巧称作动态规划。

详解动态规划

现在让我们更详细地介绍动态规划。

简而言之,我们可以说动态规划主要用来解决一些希望找到问题最优解的优化问题。

一种可以用动态规划解决的情况就是会有反复出现的子问题,然后这些子问题还会包含更小的子问题。相比于不断尝试去解决这些反复出现的子问题,动态规划会尝试一次解决更小的子问题。之后我们可以将结果输出记录在表格中,我们在之后的计算中可以把这些记录作为问题的原始解。

举个例子,斐波那契数列 0,1,1,2,3,5,8,13,…有着一个相当简单的描述方式,它的每个数字都与前两个紧邻的数字相关。如果 F(n) 是第 n 个数字,那么我们会有 F(n) = F(n-1) + F(n-2)。这个在数学上称作*递归方程*或者*递推关系*。为了计算后面的项,它需要前面项的计算结果作为输入。

拒绝遗忘:高效的动态规划算法

 

大多数动态规划问题都能被归类成两种类型:

大多数动态规划问题都能被归类成两种类型:

  • 优化问题
  • 组合问题

优化问题希望你选择一个可行的解决方案,以便最小化或最大化所需函数的值。组合问题希望你弄清楚做某事方案的数量或某些事件发生的概率。

解决方案的对比:自上而下或者自下而上

以下是两种不同的动态规划解决方案:

  • 自上而下:你从最顶端开始不断地分解问题,直到你看到问题已经分解到最小并已得到解决,之后只用返回保存的答案即可。这叫做记忆存储(*Memoization*)。
  • 自下而上:你可以直接开始解决较小的子问题,从而获得最好的解决方案。在此过程中,你需要保证在解决问题之前先解决子问题。这可以称为表格填充算法(*Tabulation,*table-filling algorithm**)。

至于迭代和递归与这两种方法的关系,自下而上用到了迭代技术,而自上而下则用到了递归技术。

拒绝遗忘:高效的动态规划算法

 

图片中的展示在理论上可能并不完全正确,但这是一种可以理解的展示方式。

这儿有一个普通方法和动态规划方法的比较,你可以看到两者时间复杂度的不同。

Memoization 的准则:不要忘记

Jeff Erickson 在他的笔记中这样描述斐波那契数列:

递归算法之所以速度慢,是因为它一遍又一遍地计算了相同的斐波那契数列。

拒绝遗忘:高效的动态规划算法

 

来自 Jeff Erickson 笔记:http://jeffe.cs.illinois.edu/

我们可以通过记录递归调用的结果来加速递归算法,这样在之后需要这些结果时就不必重新算了。

Memoization 是指缓存和重用之前计算结果的技术。

如果你使用 Memoization 来解决问题,可以通过维护已经解决的子问题的映射来实现(正如我们之前讨论的键值对映射)。你首先解决「上层」问题(通常是为了解决子问题而进行递归),这样做是「自上而下」。

*memoization*的伪代码

拒绝遗忘:高效的动态规划算法

 

因此在使用递归的过程中,我们使用额外的内存(即这里的 lookup)来执行操作以存储结果。如果查找命中存储值,我们将直接返回它,或者将其添加到特定索引。

请记住,额外的内存与表格填充之间存在一个权衡。

拒绝遗忘:高效的动态规划算法

 

自上而下的方法

Tabulation:以表格形式填充

但是一旦我们看到数组(存储的解决方案)是如何被填充的,我们就可以用一个简单的循环替换递归,这个循环有意地按顺序填充数组,而不是依赖于复杂的递归来为我们完成。

拒绝遗忘:高效的动态规划算法

 

 

来自 Jeff Erickson 的笔记:http://jeffe.cs.illinois.edu/

 

Tabulation 以「*自下而上*」的方式进行。它更直接,会计算所有值,但需要的开销更少,因为它不必维护映射并以表格形式为每个值存储数据。它还可以计算不必要的值。如果你只想计算问题的所有值,则可以使用此方法。

*tabulation*的伪代码:

拒绝遗忘:高效的动态规划算法

 

 

斐波那契树的伪代码

正如您可以在图片中看到的伪代码(右侧),它会进行迭代(即循环直到数组结束)。它从 fib(0),fib(1),fib(2),…开始,所以使用 tabulation 方法,我们可以消除递归,只需通过循环元素返回结果。

追根溯源

Richard bellman 是这个概念的提出者。他在 20 世纪 50 年代中期为兰德公司工作时想到了这一点。选择「dynamic programming」这个名字的原因是为了隐藏他为这项研究所做的数学工作。因为他担心他的老板会反对或不喜欢任何类型的数学研究。

所以「programming」这个词只是一个参考,以表明这是一种老式的计划或调度方式,通常是通过逐渐填充表格(以动态方式而不是线性方式)而不是一次全部填入的方式进行。

原文链接:https://medium.freecodecamp.org/an-intro-to-algorithms-dynamic-programming-dd00873362bb



Tags:动态规划算法   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
假设你正在使用适当的输入数据进行一些计算。你在每个实例中都进行了一些计算,以便得到一些结果。当你提供相同的输入时,你不知道会有相同的输出。这就像你在重新计算之前已经计算好的特定结果一样。...【详细内容】
2019-08-28  Tags: 动态规划算法  点击:(194)  评论:(0)  加入收藏
递归算法与动态规划算法是计算机程序设计、数据结构中常见算法。有些书籍教材中对递归算法与动态规划算法比较时,总是指出动态规划算法优于递归算法,在问题较为复杂时不建议使...【详细内容】
2019-06-19  Tags: 动态规划算法  点击:(416)  评论:(0)  加入收藏
▌简易百科推荐
前言Kafka 中有很多延时操作,比如对于耗时的网络请求(比如 Produce 是等待 ISR 副本复制成功)会被封装成 DelayOperation 进行延迟处理操作,防止阻塞 Kafka请求处理线程。Kafka...【详细内容】
2021-12-27  Java技术那些事    Tags:时间轮   点击:(1)  评论:(0)  加入收藏
博雯 发自 凹非寺量子位 报道 | 公众号 QbitAI在炼丹过程中,为了减少训练所需资源,MLer有时会将大型复杂的大模型“蒸馏”为较小的模型,同时还要保证与压缩前相当的结果。这就...【详细内容】
2021-12-24  量子位    Tags:蒸馏法   点击:(11)  评论:(0)  加入收藏
分稀疏重建和稠密重建两类:稀疏重建:使用RGB相机SLAMOrb-slam,Orb-slam2,orb-slam3:工程地址在: http://webdiis.unizar.es/~raulmur/orbslam/ DSO(Direct Sparse Odometry)因为...【详细内容】
2021-12-23  老师明明可以靠颜值    Tags:算法   点击:(7)  评论:(0)  加入收藏
1. 基本概念希尔排序又叫递减增量排序算法,它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接插入排序算法的;希尔排序是一种不稳定的排序算法...【详细内容】
2021-12-22  青石野草    Tags:希尔排序   点击:(6)  评论:(0)  加入收藏
ROP是一种技巧,我们对execve函数进行拼凑来进行system /bin/sh。栈迁移的特征是溢出0x10个字符,在本次getshell中,还碰到了如何利用printf函数来进行canary的泄露。ROP+栈迁移...【详细内容】
2021-12-15  星云博创    Tags:栈迁移   点击:(22)  评论:(0)  加入收藏
一、什么是冒泡排序1.1、文字描述冒泡排序是一种简单的排序算法。它重复地走访要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地...【详细内容】
2021-12-15    晓掌柜丶韶华  Tags:排序算法   点击:(16)  评论:(0)  加入收藏
在了解golang的map之前,我们需要了解哈希这个概念。哈希表,又称散列表(Hash table),是根据键(key)而直接访问在内存储存位置的数据结构。也就是说,它通过计算出一个键值的函数,将...【详细内容】
2021-12-07  一棵梧桐木    Tags:哈希表   点击:(14)  评论:(0)  加入收藏
前面文章在谈论分布式唯一ID生成的时候,有提到雪花算法,这一次,我们详细点讲解,只讲它。SnowFlake算法据国家大气研究中心的查尔斯·奈特称,一般的雪花大约由10^19个水分子...【详细内容】
2021-11-17  小心程序猿QAQ    Tags:雪花算法   点击:(24)  评论:(0)  加入收藏
导读:在大数据时代,对复杂数据结构中的各数据项进行有效的排序和查找的能力非常重要,因为很多现代算法都需要用到它。在为数据恰当选择排序和查找策略时,需要根据数据的规模和类型进行判断。尽管不同策略最终得到的结果完...【详细内容】
2021-11-04  华章科技    Tags:排序算法   点击:(40)  评论:(0)  加入收藏
这是我在网上找的资源的一个总结,会先给出一个我看了觉得还行的关于算法的讲解,再配上实现的代码: Original author: Bill_Hoo Original Address: http://blog.sina.com.cn/s/bl...【详细内容】
2021-11-04  有AI野心的电工和码农    Tags: KMP算法   点击:(36)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条