zoukankan      html  css  js  c++  java
  • 【干货】动态规划十问十答

    问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) || … 

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

    答:多,并且越来越多。随着CS从业与求职者的添加。并伴随大家都是“有备而来”的情况下。一般简单的反转链表之类的题目已经无法再在面试中坚挺了。因此在求职者人数与招聘名额的比例较大的情况下,公司会倾向于出更难的面试问题。

    而动态规划就是一种比較具有难度,又比較“好出”的面试问题。

    相比其它的算法与数据结构知识来说。贪心法分治法太难出题了。搜索算法往往须要耗费求职者过长的程序编写时间一般也不倾向于出,二叉树链表等问题题目并没有那么多。并且求职者也都会着重准备这一块。

    因此动态规划这一类的问题,便越来越多的出如今了面试中。 


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


    答:动态规划一般来说是“高效”的代名词,由于其解决的问题一般退而求其次的算法仅仅有搜索了。以“数字三角形”一题为样例(http://www.lintcode.com/problem/triangle/ )。在“三角矩阵”中找一条从上到下的路径,使得权值之和最小。假设使用暴力搜索的算法,那么需求穷举出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层的空间就能够被反复利用。方法很easy。把数组的第一维对2取模就能够了:f[i % 2][j] = f[(i - 1) % 2][j] + f[i % 2][j-1]。这样的方法通常能够将空间复杂度减少一个数量级。 


    问9:有什么动态规划的书籍和參考资料能够推荐么? 

    yuanbin的gitbook: 
    http://algorithm.yuanbin.me/dynamic_programming/index.html
    著名的背包九讲: 
    http://love-oriented.com/pack/
    http://vdisk.weibo.com/s/tanGyi7qM8TVE
    (也能够直接在网上搜索背包九讲) 


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

    在LintCode上包括了30余道动态规划的练习题,都是从实际的面试问题中汇总的精选练习: 
    http://www.lintcode.com/tag/dynamic-programming/

    想要更加扎实的学习动态规划算法么?

    本文作者主讲的九章算法班火热报名中!

    北京时间7.19周日早9:30-11:30(美西时间7.18周六晚6:30)。第一节课免费试听!

    报名请戳:http://www.jiuzhang.com/course/1/

    ——————

    版权声明

    本文作者:九章算法段老师。九章算法班主讲人。


    九章算法。提供算法培训、IT求职咨询,帮助很多其它中国人找到好工作。
    本文属九章算法版权全部。转载请注明以上声明。


  • 相关阅读:
    Lambada. 计算和
    adb server version (31) doesn't match this client (39) 解决方案
    python爬虫beautifulsoup4系列2
    python爬虫beautifulsoup4系列1
    利用Python攻破12306的最后一道防线
    python自动化17-JS处理滚动条
    python多线程
    python接口自动化2-发送post请求
    python接口自动化1-发送get请求 前言
    jenkens其实是代码上传工具
  • 原文地址:https://www.cnblogs.com/llguanli/p/6791217.html
Copyright © 2011-2022 走看看