【Lintcode】104. Merge K Sorted Lists

题目地址:

https://www.lintcode.com/problem/merge-k-sorted-lists/description

给定一个list,里面的元素都是链表的头结点。每个链表都是单调增的。要求返回一个链表,其为这些链表的单调增的合并。

法1:用堆。开一个最小堆,然后将所有非null的头结点加进最小堆,接着每次都从堆顶取出一个链表节点,加到最终要返回的链表的尾部,然后将那个链表节点的next节点(非null的)加进最小堆,直到所有链表都遍历完为止。代码如下:

import java.util.List;
import java.util.PriorityQueue;

public class Solution {
    /**
     * @param lists: a list of ListNode
     * @return: The head of one sorted list.
     */
    public ListNode mergeKLists(List<ListNode> lists) {
        // write your code here
        ListNode dummy = new ListNode(0), cur = dummy;
        PriorityQueue<ListNode> minHeap = new PriorityQueue<>((n1, n2) -> n1.val <= n2.val ? -1 : 1);
        // 将所有非null的链表头结点加入最小堆中
        for (ListNode head : lists) {
            if (head != null) {
                minHeap.offer(head);
            }
        }
        
        while (!minHeap.isEmpty()) {
        	// 从堆顶取出节点,加到cur后面,同时cur后移一步
        	// 接着将取出的节点的非null的next节点加进最小堆
            ListNode min = minHeap.poll();
            cur.next = min;
            cur = cur.next;
            // 要判断非null
            if (min.next != null) {
                minHeap.offer(min.next);
            }
        }
        
        return dummy.next;
    }
}

class ListNode {
    int val;
    ListNode next;
    ListNode(int val) {
        this.val = val;
    }
}

时间复杂度 O ( n log k ) O(n\log k) n n 为链表总长度, k k 为链表的个数。空间复杂度 O ( k ) O(k)

法2:分治法。如果lists长度为 1 1 ,那么直接返回这个链表就行了。否则的话,我们可以递归合并lists的左半部分链表和右半部分链表,最后再将两部分合并出来的两个链表最后做个合并即可。代码如下:

import java.util.List;

public class Solution {
    /**
     * @param lists: a list of ListNode
     * @return: The head of one sorted list.
     */
    public ListNode mergeKLists(List<ListNode> lists) {
        // write your code here
        return merge(lists, 0, lists.size() - 1);
    }
    
    // 作用是将lists从l到r部分的链表合并并返回
    private ListNode merge(List<ListNode> lists, int l, int r) {
    	// 如果[l, r]里只有一个链表,则直接返回即可
        if (l == r) {
            return lists.get(l);
        }
        
        int m = l + (r - l >> 1);
        // 递归合并左右两半部分
        ListNode l1 = merge(lists, l, m);
        ListNode l2 = merge(lists, m + 1, r);
        // 开始合并l1和l2
        ListNode dummy = new ListNode(0), cur = dummy;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                cur.next = l1;
                l1 = l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        
        cur.next = l1 != null ? l1 : l2;
		return dummy.next;
    }
}

时间复杂度 O ( n log k ) O(n\log k) ,空间复杂度 O ( log k ) O(\log k) ,递归栈深度。

时间复杂度证明:
设时间消耗为 T ( k , n ) T(k, n) ,那么: T ( k , n ) = T ( k 2 , n 1 ) + T ( k 2 , n 2 ) + O ( n ) = . . . = O ( n log k ) T(k,n)=T(\frac{k}{2},n_1)+T(\frac{k}{2},n_2)+O(n)=...=O(n\log k) 得证。

发布了354 篇原创文章 · 获赞 0 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_46105170/article/details/105308167