贪心算法|规划会议室的最大会议次数

351 阅读3分钟

前言

本文将介绍会议室最大安排会议次数的算法题,使用贪心算法和暴力两种方式进行介绍。

正文

题目描述

一些会议要占用一个会议室宣讲,会议室不能同时安排两个会议。给出每一个会议开始的时间和结束的时间。如何来安排会议的日程,要求会议室安排会议的场次最多,返回最多的会议安排次数。

示例:一场演讲从1点开始到6点结束、一个讲座从7点开始导9点结束,给出每个会议要占用会议室的开始和结束时间,根据这些时间合理安排会议室,使会议室能最大程度的安排更多的会议。

思路分析

根据题目描述,我们会得到一个二维数组,二维数组里存放着每个会议的开始和结束时间,比如:[[1,3],[1,5],[2,4],[3,6]]。

每个会议不能同时占用会议室,所以要避免会议室的冲突,例如选了[1,3]这个会议就不能选[1,5]、[2,4]这两个会议了,但是可以选[3,6]。

贪心分析

使用贪心算法解决这个题目时,打开我们野马般的思绪,分析一下可能的贪心点,比如:

  1. 哪个会议开始的早,就优先安排哪个会议
  2. 优先选择会议时间短的会议
  3. 优先选择结束时间最早的会议

第一种贪心策略是无效的,假如给出的会议是[0,24]、[1,2]、[2,3]、[3,4],按最早的优先安排的话,只能安排一个会议了,所以这个是不正确的。

第二种贪心策略也是无效的,假如给出的会议是[0,7]、[8,14]、[6,9],按持续时间短安排的话,[6,9]时间最短,但是只能安排一个会议,所以这个策略也是无效的。

第三种贪心策略是有效的,下面对第三种策略进行分析。

假如给出的会议时间为:[1,2]、[1,5]、[2,8]、[3,6]、[3,11],分析过程如下:

  • 按会议结束时间从小到大排序
  • 从排序后第一个会议开始遍历统计,如果有冲突则删掉冲突的会议
  • 接着开始统计下一个会议,如果有冲突则删掉冲突的会议
  • 依次类推,直到遍历完,剩余的会议数就是可以安排最大的会议次数

暴力递归

使用暴力递归方式判断思路比较简单,只需要对每一个会议进行遍历,如果有冲突的就去掉,如果不冲突就计数,对每一个会议都进行与其他会议比较,最后得到最大的结果就是可安排的最大会议次数。

代码实现

贪心算法

使用贪心算法代码实现如下:

先定义一个比较器,用来对会议进行排序:

public class MettingComparator implements Comparator<int[]> {
    @Override
    public int compare(int[] o1, int[] o2) {
        return o1[1] - o2[1];
    }
}

用贪心算法进行统计会议次数:

public int bestArrange(int[][] mettings) {
    Arrays.sort(mettings, new MettingComparator());
    int timeLine = 0;
    int result = 0;
    // 依次遍历每一个会议,结束时间早的会议先遍历
    for (int[] metting : mettings) {
        if (timeLine <= metting[0]) {
            result++;
            timeLine = metting[1];
        }
    }
    return result;
}

暴力递归

使用暴力递归方式,代码如下 :

public int bestArrange(int[][] mettings) {
    if (mettings == null || mettings.length == 0) {
        return 0;
    }
    return process(mettings, 0, 0);
}
public int process(int[][] mettings, int done, int timeLine) {
    if (mettings.length == 0) {
        return done;
    }
    int max = done;
    // 枚举每一个会议
    for (int i = 0; i < mettings.length; i++) {
        if (mettings[i][0] >= timeLine) {
            int[][] next = copy(mettings, i);
            max = Math.max(max, process(next, done + 1, mettings[i][1]));
        }
    }
    return max;
}
public int[][] copy(int[][] mettings, int i) {
    int[][] ans = new int[mettings.length - 1][];
    int index = 0;
    for (int k = 0; k < mettings.length; k++) {
        if (k != i) {
            ans[index++] = mettings[k];
        }
    }
    return ans;
}

总结

本文将介绍会议室最大安排会议次数的算法题,使用贪心算法和暴力两种方式进行介绍。其中使用贪心算法主要是要找到正确的贪心策略,而暴力递归的话是毫无道理可言,直接硬刚就可以了。