Leetcode 23. 合并K个排序链表

题目

合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。

示例:

输入:
[
  1->4->5,
  1->3->4,
  2->6
]
输出: 1->1->2->3->4->4->5->6

题目解析

类似合并两个有序链表,但是由于数组长度不确定,使用递归有点麻烦。

第一次

暴力实现,验证猜想和算法思路。将每一个链表比较成功后指向 next。注意哑节点思路不需要判空。

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) return null;
        ListNode root = new ListNode(-1);
        ListNode node = root;
        while(true) {
            int minIndex = -1;
            for (int i = 0; i < lists.length; i++) {
                if (lists[i] != null) {
                    if (minIndex == -1) {
                        minIndex = i;
                    } else {
                        if (lists[i].val < lists[minIndex].val) minIndex = i;
                    }
                }
            }
            if (minIndex == -1) break;
            ListNode temp = lists[minIndex];
            lists[minIndex] = temp.next;
            node.next = temp;
            node = node.next;
        }

        return root.next;
    }

}

第二次

使用 TreeMap 有序的特性,实现方式局限性比较大,空间复杂度较高(可以进行部分优化)主要理解其算法思路。

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) return null;
        Map<Integer, Integer> results = new TreeMap<>();
        for (int i = 0; i < lists.length; i++) {
            ListNode node = lists[i];
            while(node != null) {
                int count = results.getOrDefault(node.val, 0);
                results.put(node.val, ++count);
                node = node.next;
            }
        }

        ListNode root = new ListNode(-1);
        ListNode node = root;

        for (Map.Entry<Integer, Integer> entry : results.entrySet()) {
            for (int i = 0; i < entry.getValue(); i++) {
                node.next = new ListNode(entry.getKey());
                node = node.next;
            }
        }

        return root.next;
    }

}

第三次

使用优先级队列

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) return null;
        ListNode root = new ListNode(-1);
        PriorityQueue<ListNode> pq = new PriorityQueue<>((o1, o2) -> {
            return o1.val - o2.val;
        });

        for (ListNode linked : lists) {
            if (linked == null) continue;
            pq.add(linked);
        }

        ListNode node = root;
        while(!pq.isEmpty()) {
            ListNode poll = pq.poll();
            node.next = poll;
            node = node.next;
            if (poll.next != null) pq.add(poll.next);
        }

        return root.next;
    }

}

第四次

AC 递归,分解,合并 = 归并

class Solution {

    public ListNode mergeKLists(ListNode[] lists){
        if(lists.length == 0) return null;
        if(lists.length == 1) return lists[0];
        if(lists.length == 2) return mergeTwoLists(lists[0],lists[1]);

        int mid = lists.length/2;
        ListNode[] l1 = new ListNode[mid];
        for(int i = 0; i < mid; i++) l1[i] = lists[i];

        ListNode[] l2 = new ListNode[lists.length-mid];
        for(int i = mid,j=0; i < lists.length; i++,j++) l2[j] = lists[i];

        return mergeTwoLists(mergeKLists(l1),mergeKLists(l2));

    }
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        if (l1 == null) return l2;
        if (l2 == null) return l1;

        ListNode head = null;
        if (l1.val <= l2.val){
            head = l1;
            head.next = mergeTwoLists(l1.next, l2);
        } else {
            head = l2;
            head.next = mergeTwoLists(l1, l2.next);
        }
        return head;
    }
}
posted @ 2020-08-01 22:59  Haoyo  阅读(79)  评论(0)    收藏  举报