题目描述
一些项目要占用一个会议室宣讲,会议室不用同时容纳两个项目。现在给你两个长度一样的数组,starts数组代码每个会议开始的时间,ends数组代表每个会议结束的时间。
在给你一个当前时间,请你求出当日可以利用会议室宣讲的最大值。
思路分析
此题,求策略最大值。贪心算法解决。
可以考虑以下贪心策略:
1.按照最早开始的会议排序,最早开始的优先。
2.按照最短时间排序,时间最短的优先。
3.按照最早结束排序,最早结束的优先。
贪心算法是纯粹的积累经验类型的算法思想,贪心策略的正确性证明是非常困难的,几乎不可能证明正确性,因此,只能通过对数器进行验证。同时,可以举反例排除错误的贪心策略。
比如上面的:
1.如果最早开始的会议时间是最长呢?直接怼一天的话,显然不合理对吧?
2.如果最短的会议在中间呢?导致它前面的时间浪费了,后面的时间可能正好差一点不够一个会议,这样也很浪费,肯定不是最优解。
因此,排除掉1和2,此题的最优贪心算法应该就是3。
我也无法证明3是最优解,但是这题的答案就是策略3,因此,积累一下吧,贪心算法既然无法证明正确性,只能通过多看多积累,总结经验了。
代码
数据结构
public class Node {
public int start;
public int end;
public Node(int start,int end){
this.start=start;
this.end=end;
}
}
策略3的代码
//比较器,利用小根堆排序
class minEndTimeComparator implements Comparator<Node>{
@Override
public int compare(Node o1, Node o2) {
return o1.end-o2.end;
}
}
public class BestArrange {
//测试
public static void main(String[] args) {
int[] starts=new int[]{1,1,3,6};
int[] ends=new int[]{4,2,11,15};
System.out.println(bestArrange(0,starts,ends));
}
//策略3代码
public static int bestArrange(int cur,int[] starts,int[] ends){
int num=0;
Node[] nodes=new Node[starts.length];
for (int i = 0; i < starts.length; i++) {
nodes[i]=new Node(starts[i],ends[i]);
}
PriorityQueue<Node> queue =new PriorityQueue(new minEndTimeComparator());
for (int i = 0; i < nodes.length; i++) {
queue.add(nodes[i]);
}
while (!queue.isEmpty()){
if(cur<=queue.peek().start){
cur=queue.poll().end;
num++;
}else {
queue.poll();
}
}
return num;
}