【LeetCode 1353. 最多可以参加的会议数目 (Java版本)】

本来想在LeetCode写题解,没想到验证码一直收不到,那还是记录在这吧
题目见LeetCode 1353题
这个题目本身不是很难,就是要每天参加一个会议,然后看最多能参加几个会议。问题是现在多了超时限制,而增加了些题目难度。

解法一

最先想到的解法肯定是暴力解法,按照会议的结束时间排序,然后每个会议都尝试在某一天去开会,如果可以,那就把这天标记掉,然后结果加1.详细见代码:

	public static int maxEvents(int[][] events) {
        if (events == null) return 0;
        int length = events.length;
        if (length <= 1) return length;
        Arrays.sort(events, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return (o1[1] == o2[1]) ? (o1[0] - o2[0]) : o1[1] - o2[1];
            }
        });
        int ans = 0;
        //重点在于一天只能参加一个会议,开始到结束表示的是这个会议的持续时间!!!
        //重点在于哪天参加哪个会议,应该是以结束时间作为基准,因为会议结束了就不能再参加了,那就从空闲时间里挑一个早的时间
        //用一个Boolean数组,来存储每一天的状态,当天有没有参加会议,有的话为true,那当天就不能再参加别的会议了。
        boolean[] visited = new boolean[events[events.length - 1][1] + 1];
        for (int i = 0; i < length; i++) {
            int start = events[i][0];
            int end = events[i][1];
            for (int j = start; j <= end; j++) {
                if (!visited[j]) {
                    ans++;
                    visited[j] = true;
                    break;
                }
            }
        }
        return ans;
    }

根据之前说的,显而易见,这个方法是超时的。也就是LeetCode不允许使用该方法。我当时没多想,以为是数组太多,将天从Boolean改成hashset存储,结果也不行。

那明显,我们是无法存储所有会议是哪天参加这个信息的。
针对这个问题,可以采用优胜劣汰的思路,对于已经决定了哪天参加的会议,我们就抛弃掉这部分信息,只记录参加的场次。这样内存使用会大大下降。
下面的解法二,就使用了最小堆来辅助。
(为什么要先参加结束得最早的会议呢,当然是因为curDay在变大,结束时间限制了会议能被参加的时间底线)

	public static int maxEvents3(int[][] events) {
        if (events == null) return 0;
        int length = events.length;
        if (length <= 1) return length;
        Arrays.sort(events, new Comparator<int[]>() {
            @Override
            public int compare(int[] o1, int[] o2) {
                return (o1[0] == o2[0]) ? o1[1] - o2[1] : (o1[0] - o2[0]);
            }
        });
        int ans = 0;
        int curDay = events[0][0];
        int index = 0;
        PriorityQueue<Integer> queue = new PriorityQueue<>();//这个最小堆里存储curDay当天开始的会议的结束时间,如果在这天之前的都给删掉
        while (index < length || !queue.isEmpty()) {
            //进来之后先把当天之前的数据删掉,因为不能再参加了
            while (!queue.isEmpty() && queue.peek() < curDay) {
                queue.poll();
            }
            //接下来把能参加的都加进来
            while (index < length && events[index][0] == curDay) {
                queue.add(events[index++][1]);
            }
            //这时候呢,就应该取一个最早结束的会议参加下
            if (!queue.isEmpty()) {
                queue.poll();
                ans++;
            }
            //每参加一个会议,就过一天,curDay+1
            curDay++;
        }
        return ans;

    }

使用最小堆只存放会议开始时间大于等于当前天数的,只要有一条符合记录的数据,我们就可以参加一个会议(会议以结束时间存放在最小堆中),先参加的会议,肯定是结束最早的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值