算法介绍
贪心算法是一种通过局部的最优解构造全局的最优解的算法,其大体的流程可以是:
- 根据题意,选取量度标准;
- 按量度标准排序并输入;
- 判断输入是否与当前已构成的最优解可构成一个可行解。
其核心是找到最优的量度标准。可以认为是在构造解的过程中使用最小的代价,极大或极小化目标函数,从而给接下来构造解留下尽量大的空间。
例题
LeetCode 455. 分发饼干 (简单)
题目描述
有一群孩子和一堆饼干,每个孩子有一个饥饿度,每个饼干都有一个大小。每个孩子只能吃 最多一个饼干,且只有饼干的大小大于孩子的饥饿度时,这个孩子才能吃饱。求解最多有多少孩 子可以吃饱。
输入输出样例
Input: [1,2], [1,2,3]
Output: 2
解法
饥饿度越小的孩子越容易满足,我们将孩子按饥饿度由小到大排序,依次处理。为了给后面饥饿度大的孩子,留下尽可能大的饼干(这样饥饿度大的孩子有更大的机会吃饱),我们分给当前的孩子最小的但能令其吃饱的饼干。
LeetCode 435. 无重叠区间(中等)
题目描述
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:
- 可以认为区间的终点总是大于它的起点。
- 区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。
输入输出样例
输入: [ [1,2], [2,3], [3,4], [1,3] ]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。
解法
首先考虑解中最左侧的区间,其左侧没有其他区间,为了给解中剩下的区间留下尽可能大的空间,从而减少删除区间的数量,应该取最小。将与区间重叠的区间删除后,剩下的区间就构成了一个子问题,我们使用同样的处理方式求解。具体求解过程为:按区间的右边界从小到大排序,处理一个区间时,检查其是否与解中前一个区间重叠,若重叠,则将其删除;若不重重叠,则将其加入解。
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数组确定最多可以再种多少花:
- 从开始遍历,若当前位置有花,那么当前位置与下一位置都不能种植,且下一位置一定没有种植(约束条件),则;
- 若当前位置没有花,且当前已经是花坛末尾或者下一位置没有花(前一位置一定没有花),则可以种植,同时,否则。
代码
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;
}