leetcode-我的日程安排表 III

280 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情

题目描述

当 k 个日程安排有一些时间上的交叉时(例如 k 个日程安排都在同一时间内),就会产生 k 次预订。

给你一些日程安排 [start, end) ,请你在每个日程安排添加后,返回一个整数 k ,表示所有先前日程安排会产生的最大 k 次预订。

实现一个 MyCalendarThree 类来存放你的日程安排,你可以一直添加新的日程安排。

  • MyCalendarThree() 初始化对象。
  • int book(int start, int end) 返回一个整数 k ,表示日历中存在的 k 次预订的最大值。  

示例:
输入:
["MyCalendarThree", "book", "book", "book", "book", "book", "book"]
[[], [10, 20], [50, 60], [10, 40], [5, 15], [5, 10], [25, 55]]
输出:
[null, 1, 1, 2, 3, 3, 3]

解释:
MyCalendarThree myCalendarThree = new MyCalendarThree();
myCalendarThree.book(10, 20); // 返回 1 ,第一个日程安排可以预订并且不存在相交,所以最大 k 次预订是 1 次预订。
myCalendarThree.book(50, 60); // 返回 1 ,第二个日程安排可以预订并且不存在相交,所以最大 k 次预订是 1 次预订。
myCalendarThree.book(10, 40); // 返回 2 ,第三个日程安排 [10, 40) 与第一个日程安排相交,所以最大 k 次预订是 2 次预订。
myCalendarThree.book(5, 15); // 返回 3 ,剩下的日程安排的最大 k 次预订是 3 次预订。
myCalendarThree.book(5, 10); // 返回 3
myCalendarThree.book(25, 55); // 返回 3

思路

挺有意思的题目,首先要读懂题意,book方法返回的实际是重合次数最多单位时间的重合次数。我们最简单的模拟,先初始化一个大数组,每个位置的值都是0,然后每次book,就是在[start, end)的段上,每个值都加1,然后求解最大值。直接模拟有2个问题

  1. 数组需要开的非常大,按照本题条件是10^9
  2. [start, end)的段上,每个值都加1的效率很低 问题1,我们可以使用一个treeMap来记录起始位置,问题2,刚好是差分数组擅长的点。所以本题可以直接使用差分数组:用一个treeMap保存差分,没有就是0,每次book,start位置+1,end位置-1(因为end不包含,如果包含,就是end+1位置-1),这样,前k项的前缀和就是a[k]的值,每次book的时候,变化的只有[start,end]范围内的值,所以只要考虑这些值去更新max即可。

Java版本代码

class MyCalendarThree {

    TreeMap<Integer, Integer> map;

    int max;

    public MyCalendarThree() {
        map = new TreeMap<>();
        max = 0;
    }
    
    public int book(int start, int end) {
        map.put(start, map.getOrDefault(start, 0) + 1);
        map.put(end, map.getOrDefault(end, 0) - 1);
        int temp = 0;
        for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
            Integer key = entry.getKey();
            // 相当于在[start,end)范围内+1,大于end的值肯定不会被影响
            if (key > end) {
                break;
            }
            temp += entry.getValue();
            // 只有在[start,end)范围内的值才可能变化,判断这个范围内是否有值大于max,更新max就好
            if (key >= start) {
                max = Integer.max(max, temp);
            }
        }
        return max;
    }
}