leetcode 729

这题折磨了好久。。最开始想法是,把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;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值