10. 1 动态规划及贪心算法概述

这一章介绍两个重要的算法思想:动态规划和贪心。

谈到算法思想,前面已经涉及到的包括,递归,分治,当然暴力求解也是一种算法思想(关于算法思想的知识框架,可以参考算法书籍),但是许多问题最优解暴力实在解决不了或者效率低下,不够优美,这样就引出了——动态规划。


一. 概述

建议在对算法有所了解的情况下再学习。

什么是动态规划(Dynamic Programming)?动态规划的意义是什么?

首先看一下百科里对贪心的解释:

贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。

贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。

由此可见,贪心也能得到局部最优解,在一些场景下可行的。而动态规划,则是试图找到全局的最优解。

动态规划(英语:Dynamic programming,简称 DP)是一种在数学、管理科学、计算机科学、经济学和生物信息学中使用的,通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题,动态规划方法所耗时间往往远少于朴素解法。

动态规划背后的基本思想非常简单。大致上,若要解一个给定问题,我们需要解其不同部分(即子问题),再根据子问题的解以得出原问题的解。动态规划往往用于优化递归问题,例如斐波那契数列,如果运用递归的方式来求解会重复计算很多相同的子问题,利用动态规划的思想可以减少计算量。

通常许多子问题非常相似,为此动态规划法试图仅仅解决每个子问题一次,具有天然剪枝的功能,从而减少计算量:一旦某个给定子问题的解已经算出,则将其记忆化存储,以便下次需要同一个子问题解之时直接查表。这种做法在重复子问题的数目关于输入的规模呈指数增长时特别有用。

 

二. 原理

下面我们了解一下两者背后的算法内涵及二者之间的联系。

1. 分治,动态规划和贪心

分治:对于组合最优化模型,考虑是否可分成独立子问题,如果可以则可以考虑将问题分成更小的子问题(分),分别处理后再merge(治)。

动态规划:也是把大问题分解为小问题再合并,但是通过一张表记录了子问题的值减少了计算量。

贪心:在寻找最优组合时,只考虑当前最优解,再看下一步的最优解。

举个例子,比如有个箱子我要装东西,我想使箱子里东西最值钱;贪心的思想就是我先把当前最值钱的东西装进去,再看剩下的空间装最值钱的东西;暴力法,就是要考虑所有可能性,那组合方式就过多了;动态规划的思想,要记录下一些中间求解过程,减少计算量。

2. 性质

动态规划具有两个性质:1)重叠子问题  2)最优子结构

贪心算法:1)贪心选择性质  2)最优子结构

解释一下,最优子结构性质是指问题的最优解包含其子问题的最优解时,就称该问题具有最优子结构性质,重叠子问题指的是子问题可能被多次用到,多次计算,动态规划就是为了消除其重叠子问题而设计的。其实贪心算法是一种特殊的动态规划,由于其具有贪心选择性质,保证了子问题只会被计算一次,不会被多次计算,因此贪心算法其实是最简单的动态规划。

还有一个重要的性质:【无后效性】如果给定某一阶段的状态,则在这一阶段以后过程的发展不受这阶段以前各段状态的影响。

以斐波那契数列为例,F(n)=F(n - 1)+F(n - 2),这是F(n)的计算公式,我们需要知道F(n - 1)和F(n - 2),但是F(n - 1)和F(n - 2)的来历我们不关心了,也就是有这两个数就够了。

3. DP原理

贪心就没什么可说的了。DP的原理我们继续深入一下。

我们如何判断一个问题能否使用DP解决呢?—— 能将大问题拆成几个小问题,且满足无后效性、最优子结构性质。

DP的核心思想就是尽量缩小可能解空间。暴力做法是枚举所有的可能解,这是最大的可能解空间。DP是枚举有希望成为答案的解。这个空间比暴力的小得多,也就是说:DP自带剪枝。

动态规划的设计,其实就是利用最优子结构和重叠子问题性质对穷举法进行优化,通过将中间结果保存在数组中,实现用空间来换取时间交换,实现程序的快速运行。(动态规划求解时,一般都会转化为网格进行求解,而且因为是空间换时间(避免了子问题的重复计算),因此一般迭代求解)。


三. DP 算法要素

理解算法思想之后,我们离算法的实现越来越近。

还是以斐波那契数列为例,这是最简单的动态规划问题,对于求每一个F(n)我们需要知道:

1. 最优子结构,即F(n)的解包含了子问题F(n - 1)的解;

2. 状态转移方程,即递推公式 F(n)=F(n - 1)+F(n - 2),通俗理解为F(n)和子问题之间的关联公式,没有公式,求了子问题也得不到最终结果。

3. 边界,根据公式递推也总有个尽头,这时问题的边界必须明确给出而不是再递推得到。斐波那契数列,我们必须有F(1)和F(2)两个值。

 

 这一节,关键是理解贪心和动态规划的基本原理和异同;理解动态规划问题的特点,知道如何判断一个问题是否可以使用动态规划;理解DP算法的三大要素。后面将以力扣的一些题目为例,学习这两种算法。

 

你可能感兴趣的:(python数据结构与算法,Python数据结构与算法)