总结 | 动态规划十问十答

专栏 | 九章算法程序员

网址 | http://www.jiuzhang.com面试

动态规划是IT技术面试中最难的算法,不少人披荆斩棘,最终仍是跪在动态规划题目上。算法

image

今天给你们总结动态规划十问十答,快速帮你扫盲动态规划。数组

问1:动态规划是个什么鸟蛋?微信

:动态规划是一种经过“大而化小”的思路解决问题的算法。区别于一些固定形式的算法,如二分法,宽度优先搜索法,动态规划没有实际的步骤来规定第一步作什么第二步作什么。因此更加确切的说,动态规划是一种解决问题的思想。这种思想的本质是,一个规模比较大的问题(假如用2-3个参数能够表示),是经过规模比较小的若干问题的结果来获得的(经过取最大,取最小,或者加起来之类的运算)因此咱们常常看到的动态规划的核心——状态转移方程都长成这样:数据结构

  • f[i][j] = f[i - 1][j] + f[i][j - 1]学习

  • f[i] = max{f[j] if j < i and …} + 1优化

  • f[i][j] = f[0][j - 1] && judge(1,i) || f[1][j - 1] && judge(2,i) || …3d

问2:动态规划面试考得多么?code

:多。而且愈来愈多。随着CS从业与求职者的增长,并伴随你们都是“有备而来”的状况下,通常简单的反转链表之类的题目已经没法再在面试中坚挺了。所以在求职者人数与招聘名额的比例较大的状况下,公司会倾向于出更难的面试问题。而动态规划就是一种比较具备难度,又比较“好出”的面试问题。相比其余的算法与数据结构知识来讲,贪心法分治法太难出题了,搜索算法每每须要耗费求职者过长的程序编写时间通常也不倾向于出,二叉树链表等问题题目并无那么多,并且求职者也都会着重准备这一块。所以动态规划这一类的问题,便愈来愈多的出如今了面试中。

问3:动态规划快在哪儿?

:动态规划通常来讲是“高效”的代名词,由于其解决的问题通常退而求其次的算法只有搜索了。以“数字三角形”一题为例子,在“三角矩阵”中找一条从上到下的路径,使得权值之和最小。若是使用暴力搜索的算法,那么需求穷举出2^(n-1)条路径(n为三角形高度),而使用动态规划的话,则时间复杂度下降到了n^2,完成了质的飞跃。那么究竟为何这么快呢?缘由在于动态规划算法去掉了“无用和重复的运算”。在搜索算法中,假如从A->B有2条路径,一条代价为10,另一条代价为100,B->终点有1024条路径。当咱们选择了代价为10的那条路径走到B时,能够继续往下走完1024条路径到终点,可是在此以后,咱们再从代价为100的路径从A走到B时,咱们能够发现此时不管如何走,都不可能有刚才从10的路径走过来更好,因此这些计算是“无用”的计算,也能够说是“重复”的计算。这就是动态规划之因此“快”的重要缘由。

问4:学习动态规划有什么捷径?

:咱们将动态规划的常见类型分为以下几种:

  • 矩阵型

  • 序列型

  • 双序列型

  • 划分型

  • 区间型

  • 背包型

  • 状态压缩型

  • 树型

其中,在技术面试中常常出现的是矩阵型,序列型和双序列型。划分型,区间型和背包型偶尔出现。状态压缩和树型基本不会出现(通常在算法竞赛中才会出现)。

每种类型都有着本身的题目特色和状态的表示方法。以矩阵型动态规划为例,通常题目会给你一个矩阵,告诉你有一个小人在上面走动,每次只能向右和向下走,而后问你好比有多少种方案从左上走到右下 (http://www.lintcode.com/problem/unique-paths/)。这种类型状态表示的特色通常是使用坐标做为状态,如f[i][j]表示走到(i,j)这个位置的时候,一共有多少种方案。状态的转移则是考虑是从哪儿走到(i,j)这个坐标的。而序列型的动态规划,通常是告诉你一个序列;双序列的动态规划通常是告诉你两个字符串或者两个序列。

将所作过的动态规划问题按照这些类别进行归类,分析状态的表示方法和状态转移方程的构造方法在每种类型中的近似之处,会让你更快的学会动态规划。

问5:什么样的问题适合使用动态规划?

:可使用动态规划的问题通常都有一些特色能够遵循。如题目的问法通常是三种方式:

1. 求最大值/最小值

2. 求可不可行

3. 求方案总数

若是你碰到一个问题,是问你这三个问题之一的,那么有90%的几率是使用动态规划来求解。

要重点说明的是,若是一个问题让你求出“全部的”方案和结果,则确定不是使用动态规划。

问6:解决一个动态规划问题的步骤是什么?

:首先根据“问5”判断是不是动态规划的问题,若是是,则尝试将其按照“问4”进行分类,找到对应的类别和类似的问题。接着从下面的4个要素去逐步剖析解决这道题:

1. 状态是什么

2. 状态转移方程是什么

3. 状态的初始值是什么

4. 问题要求的最后答案是什么

每一个步骤分析完成以后,就基本上解决了整道动态规划的问题。

问7:怎样优化动态规划的时间?

:通常来讲,使用动态规划求解的问题,时间上已经比暴力搜索要优化不少了。可是仍然存在着一些能够优化的空间。一般来讲,动态规划的时间优化,有以下两种常见的方式:

1. 经过变换状态优化

2. 经过决策单调优化

对于经过变换状态来优化的问题比较难,须要一些经验和灵感。而对于决策单调的优化,则比较简单,但适用范围不广,通常只适用于划分型动态规划当中,一般这个方法能够将复杂度下降一个数量级。

问8:怎样优化动态规划的空间?

:动态规划的空间优化只有一种方法,就是使用滚动数组进行优化。以一个二维的动态规划为例子。假如状态转移方程以下:f[i][j] = f[i - 1][j] + f[i][j - 1]。咱们能够发现,第i层的状态,已经和第i-2层的状态没有关系了,那么这种状况下,用于存储第i-2层的空间就能够被重复利用。方法很是简单,把数组的第一维对2取模就能够了:f[i % 2][j] = f[(i - 1) % 2][j] + f[i % 2][j-1]。这种方法一般能够将空间复杂度下降一个数量级。

问9:有哪些动态规划题目必需要练习的?

在 LintCode 上包含了80余道动态规划的练习题:

www.lintcode.com/tag/dynamic…

都是从实际的面试问题中汇总的精选练习,熟练掌握这些练习题,基本上能够知足面试需求。

问10:有什么书籍和参考资料能够推荐么?

著名的《背包问题九讲》

www.kancloud.cn/kancloud/pa…

PS. 也能够直接在网上搜索背包九讲

DP 面试高频题汇总表

欢迎关注个人微信公众号:九章算法(ninechapter)。
精英程序员交流社区,按期发布面试题、面试技巧、求职信息等
2d09fefd332a1a68bb1c.jpeg
相关文章
相关标签/搜索