5: 09 一天开始
等会11:00 睡一会
我的日程安排表 leetCode
标签 : 线段树 二分查找 有序集合
实现一个 MyCalendar 类来存放你的日程安排。如果要添加的日程安排不会造成 重复预订 ,则可以存储这个新的日程安排。
当两个日程安排有一些时间上的交叉时(例如两个日程安排都在同一时间内),就会产生 重复预订 。
日程可以用一对整数 start 和 end 表示,这里的时间是半开区间,即 [start, end), 实数 x 的范围为, start <= x < end 。
实现 MyCalendar 类:
MyCalendar() 初始化日历对象。
boolean book(int start, int end) 如果可以将日程安排成功添加到日历中而不会导致重复预订,返回 true 。否则,返回 false 并且不要将该日程安排添加到日历中。
链接:https://leetcode.cn/problems/my-calendar-i
先写个暴力算法把
class MyCalendar {
List<int[]>;
public MyCalendar() {
list = new ArrayList<>();
}
//重复预定
//添加的日程安排 不会造成重复预定,则可以存储这个新的日程安排
// 当两个日程安排有一些时间上的交叉的时候,就会产生重复预订
//日程我们使用半开区间 [start,end);
//用什么数据结构来存储 这些日历是一个大问题
//线段树能干什么?
public boolean book(int start, int end) {
for(int i = 0;i <list.size();i++){
int x = Math.min(list.get(i)[0],start);
int y = Math.max(list.get(i)[1],end);
if(x <= y){
continue;
}else{
return false;
}
list.add(new int[]{start,end});
Collections.sort(list,new Compartor<int[]>(){
@Override
public int compare(int[]a1,int[]a2){
return a1[0] - a2[0];
}
});
}
}
public boolean judge(int start,int end){
}
public void add(int start, int end){
}
}
毫无疑问会超时
线段树:
二分怎么二分呢?
优先队列
PriorityQueue 可定不能二分的,还得用最开始的 list
优化一下
List<Integer>list = new ArrayList<>(); //我们的这个还在
//判断是否有重叠
int l = 0;
int r = list.size()-1;
while(l<=r){
int mid = l + (r-l)/2;
int x = Math.min(list.get(mid)[0],start);
int y = Math.max(list.get(mid)[1],end);
if(x <= y){
if(start > list.get(mid)[0]){
r = mid -1 ;
}else{
l = mid+1;
}
}else{
return false;
}
}
有序集合是什么
类似问题: 面试: java哪些集合是有序的
LinkedHashMap LinkedHashMap LinkedHashSet
这些集合在遍历的时候会保持添加的顺序,
TreeMap TreeSet 在遍历的过程会以自然顺序 输出
选做题 1.1 题
线段树的构造
难度中等
线段树是一颗二叉树,它的每个节点都包含了两个额外的属性start 和 end 用于表示该节点所代表的区间。 start 和 end 都是整数, 并按照如下的方式赋值:
- 根节点的
。。。自己去搜这道题
可能的答案
[1,6]
[1,6] [1,3] [4,6] [1,2] [2,3] [4,5] [6,6] [1,1] [2,2] [4,4,] [5,5]
public class TreeNode{
TreeNode left;
TreeNode right;
int start;
int end;
}
public TreeNode build(int start, int end){
TreeNode res = new TreeNode();
if(start == end){
res.start = start;
res.end = end;
return res;
}
res.start = start;
res.end = end;
res.left = build(start, start+end/2);
res.right = build(start+end/2+1,end);
return res;
}
选做题2 1.2线段树的查询
查询区间 内的最大值
query方法 接受三个参数 root,start ,end
public int query(TreeNode root, int start , int end){
query(root.left,start,end);
query(root.right,start,end);
}
选做题3 ,
修改二叉树 index 将一个点的值改变
后面两题选做没有体力去想了, 大概也是递归
如果有了线段树
怎么做第一题呢?
先写一个线段树
算了,我怎么方便怎么来把
如果有一个线段树,维护某个区间是否被选中是否全部备选的布尔变量那么这题还是很简单的。
当然这都是我的猜想
先写线段树的查询,再写一个修改
假设已经维护好了 istaken 变量
public boolean hastaken query(TreeNode shu , int left,
int right){
if(shu.left == left &&shu.right == right){
return shu.istaken;
}
//我们需要思考要询问的区间和当前节点的代表的区间之间的关系
int mid = (shu.left + shu.right) /2;
boolean lefttaken = false;
boolean righttaken = false;
if(left <= mid){
if(right > mid){
lefttaken = query(shu.left,left,mid);
}else{
righttaken = query(shu.left,left,right);
}
}else{
leftaken = true;
}
if(left > mid){
if(left > mid){
lefttaken = true;
righttaken = query(res.right, left,right);
}else{
righttaken = query(res.right, mid,right);
}
}
return leftaken&&righttaken;
}
猜测的代码
我觉的和query一样
public void modify(TreeNode shu ,int left, int right){
if(shu.left == left && shu.right == right){
shu.istaken = true;
}
// 还是和查询一样需要考虑shu代表的区间 和要修改的区间的 关系
int mid = (shu.left +shu.right)/2;
if(right < mid){
modify(shu,left,right);
}else{
modify(shu,left,mid);
}
if(left > mid){
modify(shu,left, right);
}else{
moidfy(shu,mid,right);
}
}
待会在调试把
有点累了。写不动了