#leetcode#Merge K Sorted Lists

本文探讨了如何使用分治策略和堆排序方法高效地合并多个已排序链表,并详细分析了每种方法的时间复杂度。通过实例演示,帮助读者理解合并过程和优化策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.



思路:

方法1, 利用merge two sorted list的方法来逐个merge, 假设K个list, 每个list的长度是n, 时间复杂度分析:

第一次merge lists[ 0 ] & lists[ 1 ], 时间复杂度是O(n + n), 

然后用list[ 2]  来merge上一次得到的长度为 2n的list, O(2n + n)

        .

.

.

最后一次merge是O( (k - 1)n + n)

可以看出这是一个等差数列, 2n, 3n, 4n, ... kn,   所以时间复杂度是O(nk^2), 但是这样太慢了, leetcode 会TLE

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        ListNode head = null;
        for(int i = 0; i < lists.length; i++){
            head = mergeTwoLists(lists[i], head);
        }
        return head;
    }
    
    private ListNode mergeTwoLists(ListNode A, ListNode B){
        if(A == null && B == null){
            return null;
        }
        if(A == null)
            return B;
        if(B == null)
            return A;
        ListNode dummy = new ListNode(0);
        dummy.next = A;
        ListNode pre = dummy;
        while(A != null && B != null){
            if(A.val < B.val){
                A = A.next;
                pre = pre.next;
            }else{
                ListNode next = B.next;
                B.next = A;
                pre.next = B;
                B = next;
                pre = pre.next;
            }
        }
        // while(B != null){
        //     pre.next = B;
        //     B = B.next;
        //     pre = pre.next;
        // }
        if(B != null)
            pre.next = B;
        
        return dummy.next;
    }
}


方法2:方法1的进阶,Divide and Conquer, 用merge sort的思想来解决问题  O(nklogk)


这里自己写的时候有个bug, 

return mergeTwoLists(helper(lists, l, m), helper(lists, m + 1, r)); 

如果写成   helper(lists,l, m - 1), helper(lists, m , r), 则当 l = 0, r = 1, m = 0, helper(lists,m,r)还是helper(lists, 0, 1), 会一直递归直到stackOverflow

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists == null || lists.length == 0){
            return null;
        }
        return helper(lists, 0, lists.length - 1);
    }
    
    private ListNode helper(ListNode[] lists, int l, int r){
        if(l < r){
            int m = l + (r - l) / 2;
            return mergeTwoLists(helper(lists, l, m), helper(lists, m + 1, r));    //这里注意左右边界的取值, 如果 (l,m -1), (m, r), 会StackOverFlow
        }
        return lists[l];
    }
    
    private ListNode mergeTwoLists(ListNode A, ListNode B){
       
        ListNode dummy = new ListNode(0);
        dummy.next = A;
        ListNode pre = dummy;
        while(A != null && B != null){
            if(A.val < B.val){
                A = A.next;
                pre = pre.next;
            }else{
                ListNode next = B.next;
                B.next = A;
                pre.next = B;
                B = next;
                pre = pre.next;
            }
        }
    
        if(B != null)
            pre.next = B;
        
        return dummy.next;
    }
}


方法3:用堆排序, 这里要自定义Comparator来排序ListNode,

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
public class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        PriorityQueue<ListNode> pq = new PriorityQueue<ListNode>(10, new Comparator<ListNode>(){
            @Override
            public int compare(ListNode a, ListNode b){
                return a.val - b.val;
            }
        });
        for(int i = 0; i < lists.length; i++){
            if(lists[i] != null)
                pq.offer(lists[i]);
        }
        ListNode dummy = new ListNode(0);
        ListNode pre = dummy;
        while(!pq.isEmpty()){
            ListNode cur = pq.poll();
            if(cur.next != null){
                pq.offer(cur.next);
            }
            pre.next = cur;
            pre = pre.next;
        }
        
        return dummy.next;
    }
}


方法2和3都是学习的code ganker大神的博客http://blog.youkuaiyun.com/linhuanmars/article/details/19899259


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值