K个排序链表的合并

问题描述;

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

示例:

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-k-sorted-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解法一:

暴力求解,遍历K个链表,找到其中头结点最小的那个,将该节点插到合并链表的尾部,该节点后移。重复上述工作直到数组中k个排序链表都为null。

实现代码如下:

    public ListNode mergeKLists(ListNode[] lists) {
        ListNode head = new ListNode(-1);
        ListNode cur = head;
        boolean flag = true;//当所有的结点都遍历完成后 置为false
        while(flag){
            flag = false;
            int minValue = Integer.MAX_VALUE;
            for(int i = 0; i < lists.length; i++){
                if(lists[i] == null){
                    continue;
                }
                flag = true;
                minValue = lists[i].val < minValue ?  lists[i].val : minValue;
            }
            for(int i = 0; i < lists.length; i++){
                if(lists[i] == null){
                    continue;
                }
                if(minValue == lists[i].val){
                    cur.next = lists[i];
                    lists[i] = lists[i].next;
                    cur = cur.next;
                }
            }
        }
        return head.next;
    }

    假设每个链表长度为N,则上述方法的时间复杂度为O(k*k* N),由于总共K*N个元素,每个元素都需要经过K轮循环。

解法二:

使用归并排序的思想,将lists数组中的链表两两合并,如此最终剩下一个大链表。为了避免开辟新空间,总是将当前数组的两端依次合并,并将结果保存在前面的位置上。该方式下每个节点不需要比较K次,只需log(K)即可。因此时间复杂度降为O(log(k) * k * N)

实现代码如下:

   
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode head = new ListNode(-1);
        ListNode cur = head;
        ListNode cur1 = l1;
        ListNode cur2 = l2;
        while(cur1 != null && cur2 != null){
            if(cur1.val < cur2.val){
                cur.next = cur1;
                cur1 = cur1.next;
            }else{
                cur.next = cur2;
                cur2 = cur2.next;
            }
            cur = cur.next;
        }
        if(cur1 != null){
            cur.next = cur1;
        }else{
            cur.next = cur2;
        }
        return head.next;
    }
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0){
            return null;
        }
        for(int end = lists.length - 1; end > 0; end = end / 2){
            step(lists, 0, end);
        }
        return lists[0];
    }
    public void step(ListNode[] lists, int start, int end){
        while(start < end){
            lists[start] = mergeTwoLists(lists[start], lists[end]);
            start++;
            end--;
        }
    }

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章