23. 合并K个升序链表 - LeetCode

23. 合并K个升序链表

题目链接

暴力合并

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length == 0) return null;
        ListNode head = new ListNode();
        ListNode p = head;
        while(true){
            boolean hasNum = false;
            int minN = 10001, minI = -1;
            for(int i = 0; i < lists.length; i++)
                if(lists[i] != null){
                    hasNum = true;
                    if(lists[i].val < minN){
                        minN = lists[i].val;
                        minI = i;
                    }
                }
            if(!hasNum) break;
            p.next = new ListNode(lists[minI].val);
            p = p.next;
            lists[minI] = lists[minI].next;
        }
        return head.next;
    }
}
  • 每次遍历所有剩余的数,找最小的
  • 时间复杂度为O(k2n),空间复杂度为O(1)

优先队列

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length == 0) return null;
        Queue<Integer> q = new PriorityQueue<>();
        for(int i = 0; i < lists.length; i++){
            while(lists[i] != null){
                q.add(lists[i].val);
                lists[i] = lists[i].next;
            }
        }
        ListNode head = new ListNode();
        ListNode p = head;
        while(!q.isEmpty()){
            p.next = new ListNode(q.poll());
            p = p.next;
        }
        return head.next;
    }
}
  • 把所有数塞到优先队列里,再取出来
  • 时间复杂度为O(kn·logkn),空间复杂度为O(kn)
  • 如果先把每个链表的第一个加入优先队列,取出后再放入第二个,时间和空间都能有所优化,但是写起来太麻烦了

分治合并

class Solution {
    public ListNode mergeKLists(ListNode[] lists){
        return merge(lists, 0, lists.length - 1);
    }

    private ListNode merge(ListNode[] lists, int l, int r){
        if (l == r) return lists[l];
        if (l > r) return null;
        int mid = (l + r) >> 1;
        return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
    }

    private ListNode mergeTwoLists(ListNode l1, ListNode l2){
        ListNode head = new ListNode();
        ListNode p = head;
        while(l1 != null && l2 != null){
            p.next = new ListNode();
            p = p.next;
            if(l1.val < l2.val){
                p.val = l1.val;
                l1 = l1.next;
            } else{
                p.val = l2.val;
                l2 = l2.next;
            }
        }
        p.next = l1 == null? l2: l1;
        return head.next;
    }
}
  • 利用之前的合并两个有序链表,按照分治排序的思想,二分后两两合并
  • 时间复杂度为O(kn·logk),空间复杂度为O(logk)(递归的栈空间)
posted @ 2021-02-05 11:17  一天到晚睡觉的鱼  阅读(59)  评论(0)    收藏  举报