1. 原理及概念
贪心算法在每一步都做出当时看起来最佳的选择,也就是说,它总是做出局部最优的选择,寄希望这样的选择能导致全局最优解(只是希望得到,不一定)
- 贪心算法不一定可以得到最优解,但对很多问题的确可以求得最优解
- 经典的贪心法实现的算法:Dijkstra算法,哈夫曼树,最小生成树算法
贪心算法的两个关键要素:
- 贪心选择性质:可以通过做出局部最优(贪心)选择来构造全局最优解,即在进行选择时,直接做出在当前问题中看来最优的选择,而不必考虑子问题的解。一个贪心算法通常是自顶向下的,进行一次又一次选择,讲给定问题的实例变得更小。
- 最优子结构性质:一个问题的最优如果包含其子问题的最优解,则称此子问题具有最优子结构性质。
2. 1353. 最多可以参加的会议数目
思路:先对会议的开始时间进行升序,因为可能会有多个会议的持续时间有重叠,当有重叠时如何选择会议?以·events= [[1,2],[2,3],[3,4],[1,2]]
为例,假设第一天选择了第一个[1,2], 那么在第二天还有一个·[1,2]和[2,3]进行选择,选择哪个呢,如果选择[2,3],那么在第三天及以后,[1,2]这个会议都不可能再被选择了,如果在第2天选择[1,2], 那么[2,3]这个会议可能还会在第3天及以后被选中。因此,当在第i天时,有多个会议在这一天可以选择,选择结束时间最早的(贪心选择)
具体思路:先对会议的开始时间进行升序,使得开始时间相同的连续排列,然后在第curDay天,讲开始时间等于curDay的都加入一个优先级队列pq,然后从优先级队列中选择结束时间最早的
class Solution {
public int maxEvents(int[][] events) {
int n=events.length;
Arrays.sort(events,(o1,o2)->o1[0]-o2[0]);
PriorityQueue<Integer> pq=new PriorityQueue<>();
int i=0;
int curDay=1;
int ans=0;
while(i<n||!pq.isEmpty()){
while(i<n&&events[i][0]==curDay){
pq.offer(events[i][1]);//加入结束时间
i++;
}
//可能当前是第5天 队列里面有结束时间为4的会议(不会被选择) 这样会影响当前的结束时间选择
while(!pq.isEmpty()&&pq.peek()<curDay){//之前遗留的结束时间小于当前时间的会议->删除
pq.poll();
}
if(!pq.isEmpty()){//讲当前堆中的最早结束时间的会议加入
pq.poll();
ans++;
}
curDay++;
}
return ans;
}
}