leetcode贪心算法刷题总结

162 阅读3分钟

算法介绍

贪心算法是一种通过局部的最优解构造全局的最优解的算法,其大体的流程可以是:

  1. 根据题意,选取量度标准;
  2. 按量度标准排序并输入;
  3. 判断输入是否与当前已构成的最优解可构成一个可行解。
    其核心是找到最优的量度标准。可以认为是在构造解的过程中使用最小的代价,极大或极小化目标函数,从而给接下来构造解留下尽量大的空间。

例题

LeetCode 455. 分发饼干 (简单)

题目描述

有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃 最多一个饼干,且只有饼干的大小大于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩 子可以吃饱。

输入输出样例

Input: [1,2], [1,2,3]
Output: 2

解法

饥饿度越小的孩子越容易满足,我们将孩子按饥饿度由小到大排序,依次处理。为了给后面饥饿度大的孩子,留下尽可能大的饼干(这样饥饿度大的孩子有更大的机会吃饱),我们分给当前的孩子最小的但能令其吃饱的饼干。

LeetCode 435. 无重叠区间(中等)

题目描述

给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:

  1. 可以认为区间的终点总是大于它的起点。
  2. 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。

输入输出样例

输入: [ [1,2], [2,3], [3,4], [1,3] ]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。

解法

首先考虑解中最左侧的区间[li,ri][l_i,r_i],其左侧没有其他区间,为了给解中剩下的区间留下尽可能大的空间,从而减少删除区间的数量,rir_i应该取最小。将与区间[li,ri][l_i,r_i]重叠的区间删除后,剩下的区间就构成了一个子问题,我们使用同样的处理方式求解。具体求解过程为:按区间的右边界从小到大排序,处理一个区间时,检查其是否与解中前一个区间重叠(lj>ri)(l_j > r_i),若重叠,则将其删除;若不重重叠,则将其加入解。

LeetCode 605. 种花问题(简单)

题目描述

假设有一个很长的花坛,一部分地块种植了花,另一部分却没有。可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去。

给你一个整数数组  flowerbed 表示花坛,由若干 0 和 1 组成,其中 0 表示没种植花,1 表示种植了花。另有一个数 n ,能否在不打破种植规则的情况下种入 n 朵花?能则返回 true ,不能则返回 false。

输入输出示例

输入:flowerbed = [1,0,0,0,1], n = 1
输出:true
输入:flowerbed = [1,0,0,0,1], n = 2
输出:false

解法

从贪心的角度来讲,就是种尽可能多的花,比较其与n的大小。通过遍历flowerbed数组确定最多可以再种多少花:

  1. i=0i=0开始遍历,若当前位置有花,那么当前位置与下一位置都不能种植,且下一位置一定没有种植(约束条件),则i=i+2i=i+2;
  2. 若当前位置没有花,且当前已经是花坛末尾或者下一位置没有花(前一位置一定没有花),则可以种植,同时i=i+2i=i+2,否则i=i+3i=i+3

代码

bool canPlaceFlowers(vector<int>& flowerbed, int n) {
    for ( int i = 0; i < flowerbed.size(); )
    {
        if (flowerbed[i] == 0)
        {
            if (i == flowerbed.size() - 1 || flowerbed[i+1] == 0)
            {
                --n == 0;
                i += 2;
            }
            else
                i += 3;
        }
        else
            i += 2;
    }
    return n <= 0? true : false;
}