这题折磨了好久。。最开始想法是,把start和end封装成一个int[2],然后按照一定规则排序,一开始用的PriorityQueue,但是它只是一个大根堆,用toArray方法把元素取出来,并不会按照预期全部排好序。
所幸自己写一个链表结构,每个节点有三个属性,start、end和next指针,每次插入之后,把所有节点的start和end拿出来,应当是一个不递减序列,例如(1,2),(3,4),(5,6)这样。简单说,每个节点的start不小于前一个节点的end(如果有前一个节点),且该节点end不大于后一个节点的start(如果有后一个节点)。
插入分为头插、尾插和中间插,所以需要head和tail两个指针。每次调用book时,若链表为空,直接插入,更新head和tail指针,如果end <= 头节点的start,头插法,更新head指针,不更新tail!
否则从头找到最靠右并且end <= 当前start的节点,如果是最后一个节点就尾插,更新tail,否则就是中间插入一个节点。
意外的挺快。。因为每次调book时最差都要遍历整个链表,以为会很慢。。
class MyCalendar {
static class CalenderNode{
int start;
int end;
CalenderNode next;
public CalenderNode(int start, int end){
this.start = start;
this.end = end;
}
}
CalenderNode head;
CalenderNode tail;
public MyCalendar() {
}
public boolean book(int start, int end) {
//队列为空,在头部新插一个节点,更新head tail
if(head == null){
CalenderNode newHead = new CalenderNode(start, end);
head = newHead;
tail = newHead;
return true;
}
//队首节点.start,在头部新插一个节点
if(end <= head.start){
CalenderNode newHead = new CalenderNode(start, end);
newHead.next = head;
head = newHead;
return true;
}
//找到第一个end小于当前start的节点
CalenderNode nextNode = head;
CalenderNode cur = null;
while(nextNode != null && nextNode.end <= start){
cur = nextNode;
nextNode = nextNode.next;
}
//是最后一个节点,则在队列尾部插入新节点
if(nextNode == null && cur.end <= start){
CalenderNode newTail = new CalenderNode(start, end);
tail.next = newTail;
tail = newTail;
return true;
}
//看看新节点能不能插进去,必须满足前一节点end <= start && end <= 后一节点start
//System.out.println(cur.start+" "+cur.end+" "+nextNode.start+" "+nextNode.end);
if(end <= nextNode.start){
CalenderNode newMid = new CalenderNode(start, end);
cur.next = newMid;
newMid.next = nextNode;
return true;
}
return false;
}
}