经过了前面对于贪心算法概念的理解以及简单的两道例题的学习,我对于贪心算法有了一定的认识,接下来继续学习一些简单的使用贪心算法解决的问题。例如今天的会议安排问题。
问题描述:在会议安排中,每个会议i都有起始时间bi以及结束时间ei,并且bi<ei。如果存在两个会议i,j,[bi,ei),[bj,ej)均在“有限的时间”内并且不相交,就称会议i与会议j相容。会议安排问题要求在所给的会议集合中选出最大的相容活动子集,即尽可能在有限的时间内召开更多的会议。
贪心策略选择:每次从剩下的未安排会议中选择具有最早结束时间且与已安排的会议相容的会议安排,这样可以尽快安排下一个会议。
算法设计:1.将会议的开始时间与结束时间结构化存储,并按结束时间从小到大排序。
2.选择最早结束时间的会议作为第一个会议,然后从剩下的开始时间晚于上一个会议且结束时间在剩下的会议中最早的会议中依次选择。
题目数据:
会议 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
开始时间 | 3 | 1 | 5 | 2 | 5 | 3 | 8 | 6 | 8 | 12 |
结束时间 | 6 | 4 | 7 | 5 | 9 | 8 | 11 | 10 | 12 | 14 |
解题过程:首先按照结束时间排序:
会议 | 2 | 4 | 1 | 3 | 6 | 5 | 8 | 7 | 9 | 10 |
开始时间 | 1 | 2 | 3 | 5 | 3 | 5 | 6 | 8 | 8 | 12 |
结束时间 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 14 |
然后可以看到,根据我们的贪心策略,我们会依次选择会议2,3,7,10。这也就是这个问题的最优解。接下来给出Java代码实现。
1 public int[] Solution3(){ 2 int[] meets=new int[]{1,2,3,4,5,6,7,8,9,10}; 3 int[] start_time=new int[]{3,1,5,2,5,3,8,6,8,12}; 4 int[] end_time=new int[]{6,4,7,5,9,8,11,10,12,14}; 5 Meeting[] meetings=new Meeting[meets.length]; 6 for(int i=0;i<meets.length;i++){ 7 meetings[i]=new Meeting(meets[i],start_time[i],end_time[i]); 8 } 9 Arrays.sort(meetings);//将所有会议以结束时间从小到大排序 10 int endTime=0;//用于记录上一次选择的会议的结束时间 11 ArrayList<Integer> integers=new ArrayList<>();//存储选择的会议编号方便返回 12 for (Meeting m:meetings 13 ) { 14 if(m.getStrart_Time()>endTime){ 15 integers.add(m.getMeeting_number()); 16 endTime=m.getEnd_Time(); 17 } 18 }//遍历排好序的数组,如果当前会议的开始时间大于结束时间就选择,否则不选 19 int[] result=new int[integers.size()]; 20 for (int i=0;i<integers.size();i++){ 21 result[i]=integers.get(i); 22 } 23 return result; } 24 public class Meeting implements Comparable<Meeting>{ 25 private int Meeting_number;//这个会议的序号 26 private int Start_Time; 27 private int End_Time; 28 public Meeting(int i1,int i2,int i3){ 29 this.Meeting_number=i1; 30 this.Start_Time=i2; 31 this.End_Time=i3; 32 } 33 34 public int getStrart_Time() { 35 return Start_Time; 36 } 37 38 public int getMeeting_number() { 39 return Meeting_number; 40 } 41 42 public int getEnd_Time() { 43 return End_Time; 44 } 45 46 public int compareTo(Meeting meeting){ 47 if(this.End_Time>meeting.getEnd_Time()){ 48 return 1;} 49 else if(this.End_Time==meeting.getEnd_Time()){ 50 if(this.Start_Time>meeting.Start_Time){ 51 return -1; 52 } 53 }else if(this.End_Time<meeting.End_Time){ 54 return -1; 55 } 56 return 0; 57 } 58 59 }//用于解决会议安排问题的辅助类
最终返回值{2,3,7,10},时间复杂度为O(nlogn)