Greedy Algorithm - tenji/ks GitHub Wiki

贪心算法

一、概念

贪心的意思在于在作出选择时,每次都要选择对自身最为有利的结果,保证自身利益的最大化。贪心算法就是利用这种贪心思想而得出一种算法。

贪心算法作为五大算法之一(分治、动态规划、贪心、回溯、分支界定),在数据结构中的应用十分广泛。例如:在求最小生成树的 Prim 算法中,挑选的顶点是候选边中权值最小的边的一个端点。在 Kruskal 算法中,每次选取权值最小的边加入集合。在构造霍夫曼树的过程中也是每次选择最小权值的节点构造二叉树。这种每次在执行子问题的求解时,总是选择当前最优的情形,恰好符合贪心的含义。

贪心算法可以简单描述为:大事化小,小事化了。对于一个较大的问题,通过找到与子问题的重叠,把复杂的问题划分为多个小问题。并且对于每个子问题的解进行选择,找出最优值,进行处理,再找出最优值,再处理。也就是说贪心算法是一种在每一步选择中都采取在当前状态下最好或最优的选择,从而希望得到结果是最好或最优的算法。

贪心算法在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,所做出的仅是在某种意义上的局部最优解。贪心算法不是对所有问题都能得到整体最优解,但对范围相当广泛的许多问题他能产生整体最优解或者是整体最优解的近似解。

二、与动态规划的区别

动态规划具有两个性质:

  1. 重叠子问题
  2. 最优子结构

贪心算法:

  1. 贪心选择性质
  2. 最优子结构

最优子结构性质是指问题的最优解包含其子问题的最优解时,就称该问题具有最优子结构性质,重叠子问题指的是子问题可能被多次用到,多次计算,动态规划就是为了消除其重叠子问题而设计的。(也正是因为可能需要多次用到子问题,因此动态规划需要缓存子问题的解)

其实贪心算法是一种特殊的动态规划,由于其具有贪心选择性质,保证了子问题只会被计算一次,不会被多次计算,因此贪心算法其实是最简单的动态规划。

三、算法流程

  1. 建立数学模型来描述问题;
  2. 把求解的问题分成若干个子问题;
  3. 对每一子问题求解,得到子问题的局部最优解;
  4. 把子问题的局部最优解合成原来问题的一个解。

四、伪代码

从问题的某一初始解出发
    while (能朝给定总目标前进一步) 
        do
            选择当前最优解作为可行解的一个解元素;
    由所有解元素组合成问题的一个可行解。

五、分析样例

5.1 题目描述

5.2 题目分析

5.3 代码实现

六、Leecode 题目

参考链接