题目来源:https://leetcode.cn/problems/my-calendar-i/

大致题意:
设置一个 MyCalendar 类,包含以下功能:

  • MyCalendar() 初始化日历对象。
  • boolean book(int start, int end) 如果可以将日程安排成功添加到日历中而不会导致重复预订,返回 true 。否则,返回 false 并且不要将该日程安排添加到日历中。

思路

使用线段树存下日程,每添加一次日程,将日程对应的区间在线段树中做标记。每次添加前,先检查当前日程区间内是否有被添加过的时间段,若有则不添加该日程。

因为线段树使用节点数目约是节点范围的 4 倍,而本体节点范围为 [0, 109],范围过大,不适合直接申请空间。所以采用了动态开点的方法,每放入一个日程,动态创建与日程区间相关的线段树节点。并使用懒标记标注当前节点所覆盖区间是否都已经安排过日程。

具体添加日程的操作如下:

  1. 先判断日程对应区间内是否有被添加过,查询时可以通过懒标记和查询区间内是否已经创建过节点判断:若有懒标记或者查询区间内有节点被创建,则该区间一定有被添加过的时间段
  2. 若整个区间没有被插入过,则动态开点插入该日程

代码:

public class MyCalendar_SegmentTree {Set<Integer> tree;  // 表示节点范围内有被预定的区间Set<Integer> lazy;  // 表示节点范围内都被预定int BORDER; // 节点最大范围public MyCalendar_SegmentTree() {tree = new HashSet<>();lazy = new HashSet<>();BORDER = (int) 1e9;}public boolean book(int start, int end) {// 首先查询当前日程区间内是否有被插入过if (query(start, end - 1, 0, BORDER, 1)) {return false;}// 插入当前日程update(start, end - 1, 0, BORDER, 1);return true;}/*** 查询 [start, end] 区间是否有线段树节点,若有则表示该区间内有被预定的部分** @param start* @param end* @param l     当前线段树节点的左边界* @param r     当前线段树节点的右边界* @param idx   当前线段树节点编号* @return*/public boolean query(int start, int end, int l, int r, int idx) {// 当前线段树节点不包含查询范围if (r < start || end < l) {return false;}// 若节点范围都被预定过,直接返回 trueif (lazy.contains(idx)) {return true;}// 当前线段树节点的范围都在查询范围内if (start <= l && r <= end) {// 那么只要线段树节点存在,就表示该线段树节点范围被预定过return tree.contains(idx);}int mid = (l + r) >> 1;// 查询范围只在线段树左节点中if (end <= mid) {return query(start, end, l, mid, idx * 2);} else if (mid < start) { // 查询范围只在线段树右节点中return query(start, end, mid + 1, r, idx * 2 + 1);} else {    // 查询范围横跨线段树两个子节点return query(start, end, l, mid, idx * 2) || query(start, end, mid + 1, r, idx * 2 + 1);}}/*** 预定区间 [start, end]** @param start* @param end* @param l     当前线段树节点左边界* @param r     当前线段树节点右边界* @param idx   当前线段树节点编号*/public void update(int start, int end, int l, int r, int idx) {if (r < start || end < l) {return;}// 当前线段树节点的范围都在更新范围内if (start <= l && r <= end) {tree.add(idx);lazy.add(idx);} else {int mid = (l + r) >> 1;if (mid >= end) {   // 更新范围只在线段树左节点update(start, end, l, mid, idx * 2);} else if (mid < start) {   // 更新范围只在线段树右节点update(start, end, mid + 1, r, idx * 2 + 1);} else {    // 更新范围横跨线段树左右节点update(start, end, l, mid, idx * 2);update(start, end, mid + 1, r, idx * 2 + 1);}// 当前线段树节点范围中有区间被预定tree.add(idx);}}public static void main(String[] args) {MyCalendar_SegmentTree tree = new MyCalendar_SegmentTree();System.out.println(tree.book(10, 20));System.out.println(tree.book(15, 25));System.out.println(tree.book(20, 30));}
}

力扣 729. 我的日程安排表 I相关推荐

  1. 力扣:我的日程安排表I

    package com.算法专练.力扣.我的日程安排表I;import java.util.ArrayList; import java.util.List;/*** @author xnl* @De ...

  2. 力扣 731. 我的日程安排表 II

    题目来源:https://leetcode.cn/problems/my-calendar-ii/ 大致题意: 设计一个日程类 MyCalendar,包含以下功能: 有一个 book(int star ...

  3. ​力扣解法汇总731-我的日程安排表 II

    目录链接: 力扣编程题-解法汇总_分享+记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣 描 ...

  4. ​力扣解法汇总732-我的日程安排表 III

    目录链接: 力扣编程题-解法汇总_分享+记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣 描 ...

  5. LeetCode 729. 我的日程安排表 I(set 二分查找)

    文章目录 1. 题目 2. 解题 2.1 set 二分查找 2.2 差分思想 1. 题目 实现一个 MyCalendar 类来存放你的日程安排.如果要添加的时间内没有其他安排,则可以存储这个新的日程安 ...

  6. 力扣编程题-解法汇总

    一.力扣链接: 题库 - 力扣 (LeetCode) 全球极客挚爱的技术成长平台 备注:以后每个工作日从前往后刷一道题,然后再加一道每日新题.每天两道题. 二.模版: 标题: 力扣解法汇总5-正则表达 ...

  7. LeetCode 力扣算法题解汇总,All in One

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: https://fuxuemingzhu.cn 关键词:LeetCode,力扣,算法,题解,汇总,解析 把自己刷过的所有题目做一个整理, ...

  8. 力扣小练习(Java)

    目录 797.回溯,dfs 进制转换 232栈,队列 41 13dfs 7递归 343,dp 3,滑动窗口 76,最小覆盖字串<滑动窗口> 239,滑动窗口最大值 59,螺旋矩阵Ⅱ 螺旋矩 ...

  9. 力扣1002.查找常用字符

    力扣 1002. 查找常用字符 本人力扣练习已上传至码云,可互相学习借鉴. 难度-简单 题目: 给定仅有小写字母组成的字符串数组 A,返回列表中的每个字符串中都显示的全部字符(包括重复字符)组成的列表 ...

最新文章

  1. python检查_python设置检查点简单实现
  2. SQL创建表语句文档
  3. 模式识别开发之项目---基于人头检测的人流量监测
  4. asp.net 添加成功弹出个div提示_Word双栏目录怎么做,这3个步骤早知道,让人眼前一亮...
  5. 温州大学《机器学习》课程课件(八、集成学习)
  6. ExtJS4.2学习(10)分组表格控件--GroupingGrid(转)
  7. 利用Azure communication service实现跟Teams同样等级的沟通协作应用
  8. Unity 动态切换天空盒\反射天空盒材质
  9. java重载静态方法_在Java中可以重载或覆盖静态方法吗
  10. windows双系统完全删除ubuntu
  11. 知客CRM成功客户专访----厦门英斯捷
  12. 盘点一道使用Python编程来实现高斯计算的基础算术题目
  13. 微软2008年7月「最有价值专家」(MVP)当选名单
  14. Layui多文件上传,java后台(servlet实现)
  15. 基于Python的人脸识别(68个识别点)和焦点人物检测
  16. MixPanel -Android 端埋点技术研究
  17. Android Studio生成keystore签名文件
  18. 全球游戏收入将随着电影电视改编作品的不断增多而达到惊人水平 | 美通社头条...
  19. css两张图片重叠显示
  20. 统计学中的P值与显著性的意义

热门文章

  1. 华为ensp模拟器实验:端口安全绑定MAC地址ip地址
  2. Shell编程——循环(for、while、until、break与continue)
  3. Fiddler手机抓包(iPhone)
  4. 原生JS 扫雷游戏 自动插旗子 自定义雷区大小 雷数可调
  5. linux中cd / cd~ 区别
  6. Python数组遍历的简单实现方法
  7. SCU - 4438 KMP
  8. 在函数中利用scanf为结构体数组赋值
  9. php手机省电,看完这些“技巧”,我想可以帮你有效的帮手机省电,延长续航
  10. python如何把数据写入excel表格中指定列