分治、动态规划和贪心

来源:互联网 发布:redis消息队列 php 编辑:程序博客网 时间:2024/06/15 07:34


一、分治

概念

分治,字面上的解释是“分而治之”,就是把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题……直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。

设计过程

Divide:整个问题划分为多个子问题

Conquer:求解各子问题(递归调用子问题的算法)

Combine:合并子问题的解, 形成原始问题的解

分析过程

建立递归方程

T(n)= aT(n/b)+D(n)+C(n)

Divide时间复杂度:D(n)

Conquer时间复杂度:aT(n/b)

Combine:C(n)

当n<c, T(n)=θ(1)

递归方程求解

 

与动态规划的区别是划分的子问题不相关(不存在公共子问题),而动态规划划分的子问题是相关性越大越好(存在公共子问题)。

 

治法的关键是算法的Combine。究竟应该怎样合并,目前没有统一的模式,因此需要对具体问题进行具体分析,以得出比较好的合并算法。

 

适用分治思想的算法:二分搜索、归并排序、快速排序、大整数乘法、Strassen矩阵乘法、汉诺塔、第K小元素、最近点对、快速傅里叶变换等。

 

拿到一个问题,首先想想问题的规模是否可以缩小到一定的规模就可以较容易地解决,是否具有最优子结构性质,是否合并问题分解出的子问题的解可以得到问题的解,子问题之间是否相互独立。

 

二、动态规划

概念

与分治法类似,动态规划法也是把问题一层一层地分解为规模逐渐减小的同类型的子问题。动态规划通常用来求最优化问题。此类问题可以有很多可行解,我们求出的是一个最优解,因为可能存在多个最优解。

分治法

子问题是相互独立的,若不独立,将重复计算

动态规划

可分为多个相关子问题,子问题的解被重复使用,子问题只求解一次,结果保存在表中,以后用到时直接存取

 

动态规划的条件

最优子结构

当一个问题的最优解包含了子问题的最优解时,称这个问题具有最优子结构

重叠子问题

在问题的求解过程中,很多子问题的解将被多次使用

 

步骤

1. 刻画一个最优解得结构特征

2. 递归地定义最优解的值

3. 计算最优解的值,通常采用自底向上的方法

4. 利用计算出的信息构造一个最优解

这里自底向上也可以改成自顶向下构造表法,即在递归地过程中计算子问题,若子问题的结果在表中出现则直接使用不用计算,否则计算后更新表。

 

问题一般采用动态规划法,当具有:

1)最优子结构性质时

2)高度重复性

若问题不是NP-hard问题

进一步分析后就有可能获得效率较高的算法。

若问题本身就是NP-hard问题

那么与其它的精确算法相比,动态规划法性能一般不算太坏

 

适用动态规划思想的算法:矩阵连乘、钢条切割、最长公共子序列、最优二叉搜索树、流水作业调度、0/1背包问题等。

 

三、贪心

概念

贪心算法的基本思想

求解最优化问题的算法包含一系列步骤,每一步都有一组选择,作出在当前看来最好的选择,希望通过作出局部最优选择达到全局最优选择

贪心算法不一定总产生最优解,贪心算法是否产生优化解,需严格证明

 

贪心算法产生最优解的条件:最优子结构、贪心选择性

最优子结构

当一个问题的最优解包含子问题的最优解时,称这个问题具有最优子结构

贪心选择性

当一个问题的全局最优解可以通过局部最优解得到,称这个问题具有贪心选择性

 

证明思路:

假定首选元素不是贪心选择所要的元素,证明将首元素替换成贪心选择所需元素,依然得到最优解。数学归纳法证明每一步均可通过贪心选择得到最优解

 

动态规划和贪心算法的区别

动态规划方法可用的条件:最优子结构、子问题重叠性

贪心算法产生最优解的条件:最优子结构、贪心选择性

适用贪心算法时,动态规划可能不适用。适用动态规划时,贪心算法可能不适用。

动态规划和贪心算法比较容易混淆,我的理解是动态规划是计算所有的子问题,每执行完一个步骤可能会产生多个子问题,而贪心算法则是保证每次需要解决的子问题只有一个,只需选择当下看上去最优的选择。

 

适用贪心思想的算法:活动选择问题、哈夫曼编码问题、最小生成树问题、单源最短路径问题等。

 

分治、动态规划和贪心是算法中比较常见的思想,对于具体的问题还需要具体分析问题,并且通过实践加强学习这些算法思想。


原创粉丝点击