leetcode729.我的日程安排表1

本文介绍了一个名为MyCalendar的日程管理类的设计与实现,该类能够避免日程安排的重复预订,通过使用TreeMap数据结构进行高效的时间段管理。

问题描述

实现一个 MyCalendar 类来存放你的日程安排。如果要添加的时间内没有其他安排,则可以存储这个新的日程安排。

MyCalendar 有一个 book(int start, int end)方法。它意味着在 start 到 end 时间内增加一个日程安排,注意,这里的时间是半开区间,即 [start, end), 实数 x 的范围为, start <= x < end。

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

每次调用 MyCalendar.book方法时,如果可以将日程安排成功添加到日历中而不会导致重复预订,返回 true。否则,返回 false 并且不要将该日程安排添加到日历中。

请按照以下步骤调用 MyCalendar 类: MyCalendar cal = new MyCalendar(); MyCalendar.book(start, end)

示例 1:

MyCalendar();
MyCalendar.book(10, 20); // returns true
MyCalendar.book(15, 25); // returns false
MyCalendar.book(20, 30); // returns true


解释: 
第一个日程安排可以添加到日历中.  
第二个日程安排不能添加到日历中,因为时间 15 已经被第一个日程安排预定了。
第三个日程安排可以添加到日历中,因为第一个日程安排并不包含时间 20 。

说明:

每个测试用例,调用 MyCalendar.book 函数最多不超过 100次。
调用函数 MyCalendar.book(start, end)时, start 和 end 的取值范围为 [0, 10^9]。

 

import java.util.Comparator;
import java.util.Map;
import java.util.TreeMap;

public class MyCalendar1 {
    TreeMap<Integer, Integer> treeMap = null;

    public MyCalendar1() {
        treeMap = new TreeMap<>(Comparator.naturalOrder());
    }

    public boolean book(int start, int end) {
        if (end <= start) {
            return false;
        }

        for (Map.Entry<Integer, Integer> entry : treeMap.entrySet()) {
            if (start >= entry.getValue()) {
                break;
            }
            if(end <= entry.getKey()){
                continue;
            }

            if (start < entry.getValue() || end > entry.getKey()) {
                return false;
            }
        }

        treeMap.put(start, end);
        return true;
    }
}

 

 

### 日程安排 III 的算法题解与实现方案 #### 背景介绍 日程安排 III 是 LeetCode 上的一道经典问题,目标是在多次调用 `book` 方法时动态维护一个时间区间内的最大重叠次数。此问题可以通过 **差分数组** 和 **线段树** 来解决。 --- #### 解决方法一:差分数组 ##### 原理说明 差分数组是一种高效处理区间加减操作的数据结构。通过记录区间的起点和终点的变化量,在最后遍历时累加这些变化量即可得到任意时刻的重叠次数[^3]。 ##### 实现代码 (C++) 以下是基于 C++ 的差分数组实现: ```cpp class MyCalendarThree { public: map<int, int> diff; MyCalendarThree() {} int book(int start, int end) { diff[start]++; diff[end]--; int maxK = 0; int currentOverlap = 0; for (auto &[key, value] : diff) { currentOverlap += value; maxK = std::max(maxK, currentOverlap); } return maxK; } }; ``` 上述代码中,每次调用 `book(start, end)` 会更新差分数组中的两个位置,并在最后计算当前的最大重叠次数。 --- #### 解决方法二:线段树 ##### 原理说明 线段树适用于频繁查询和修改区间的情况。对于本问题,我们可以构建一棵覆盖整个时间范围的线段树,节点存储该区间内的最大重叠次数。在线段树上执行区间增加操作并实时更新最大值[^5]。 ##### 实现代码 (Python) 以下是基于 Python 的线段树实现: ```python from collections import defaultdict class Node: def __init__(self): self.max_overlap = 0 self.lazy_add = 0 class SegmentTree: def __init__(self): self.tree = defaultdict(Node) def update(self, node_id, left, right, start, end, val): if end < left or start > right: return if start <= left and right <= end: self.tree[node_id].max_overlap += val self.tree[node_id].lazy_add += val return mid = (left + right) // 2 self.update(node_id * 2, left, mid, start, end, val) self.update(node_id * 2 + 1, mid + 1, right, start, end, val) self.tree[node_id].max_overlap = max( self.tree[node_id * 2].max_overlap, self.tree[node_id * 2 + 1].max_overlap ) + self.tree[node_id].lazy_add class MyCalendarThree: def __init__(self): self.st = SegmentTree() def book(self, start: int, end: int) -> int: self.st.update(1, 0, 10**9, start, end - 1, 1) return self.st.tree[1].max_overlap ``` 在此实现中,我们假设时间范围为 `[0, 1e9]` 并初始化了一棵线段树。每次调用 `book` 更新对应的时间区间,并返回全局最大值。 --- #### 时间复杂度分析 - **差分数组**: 单次 `book` 操作的时间复杂度为 \(O(n)\),其中 \(n\) 示已有的不同时间节点数量。 - **线段树**: 单次 `book` 操作的时间复杂度为 \(O(\log R)\),其中 \(R\) 示时间范围大小。 因此,当数据规模较大时,线段树通常现更优[^4]。 --- #### 结果验证 以下是一组测试样例及其预期结果: | 输入 | 输出 | |------|------| | `myCalendarThree.book(10, 20)` | 1 | | `myCalendarThree.book(50, 60)` | 1 | | `myCalendarThree.book(10, 40)` | 2 | | `myCalendarThree.book(5, 15)` | 3 | 以上结果均符合预期[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值