贪心算法满足两个性质:
(1)贪心选择性质
指的是原问题的整体最优解可以通过一系列局部最优的选择得到。运用同一个规则,将原问题变为一个相似的但规模更小的子问题,而后每一步都是当前最优的选择,这种选择依赖已作出的选择,但不依赖于未作出的选择。
(2)最优子结构性质
当一个问题的最优解包含其子问题的最优解时,称此问题具有最优子结构性质。
贪心算法重要的三个点:
(1)贪心策略
确定贪心策略,选择一个当前看上去最好的一个方案。有时候你可能能找到好几个方案,需要比较哪个方案是当前最好的。
(2)局部最优解
根据贪心策略,得到局部最优解。
(3)全局最优解
把所有的局部最优解合成为一个最优解。
不是贪心算法像冒泡排序,而是冒泡排序使用了贪心算法。
证明:
严谨使用贪心法求解最优化问题需要对采取的策略进行证明。证明的一般思路是使用反证法及数学归纳法,即假设策略不能导致最优解,然后通过一系列推到来得到矛盾,从而能证明此策略是最优的!
会议安排问题
贪心策略
(1)从剩下未安排的会议中选择会议具有最早开始时间且与已安排的会议相容的会议安排,以增大时间资源的利用率。 False
(2)从剩下未安排的会议中选择会议持续时间最短且与已安排的会议相容的会议安排 False
(3)从剩下未安排的会议中选择会议具有最早结束时间且与已安排的会议相容的会议安排 Right
采用贪心策略,每次从剩下的会议中选择具有最早结束时间且与已安排的会议相容的会议安排。
区间贪心
注意:
可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。
示例 1:
输入: [ [1,2], [2,3], [3,4], [1,3] ]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。
示例 2:
输入: [ [1,2], [1,2], [1,2] ]
输出: 2
解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。
示例 3:
输入: [ [1,2], [2,3] ]
输出: 0
解释: 你不需要移除任何区间,因为它们已经是无重叠的了。
题目链接:https://leetcode-cn.com/problems/non-overlapping-intervals
采取的策略:保留结尾小且不相交的区间。(其实还可以先选择左端点最大的区间)
代码:
class Solution {
public:
int eraseOverlapIntervals(vector<vector<int>>& intervals) {
if(intervals.empty())
return 0;
int n = intervals.size();
sort(intervals.begin(),intervals.end(),[](vector<int> a,vector<int> b){
return a[1] < b[1];
});
int total = 0,prev = intervals[0][1];
for(int i=1;i<n;++i){
if(intervals[i][0] < prev)
++total;
else
prev = intervals[i][1];
}
return total;
}
};