23. 合并K个排序链表_合并k个数组

16 篇文章 0 订阅
7 篇文章 0 订阅
本文探讨了如何合并k个已排序的链表,提供了三种方法:顺序合并、分治合并和使用优先队列(最小堆)。详细分析了每种方法的时间复杂度,其中分治合并和最小堆方法具有较好的效率,分别为O(nlogk)。
摘要由CSDN通过智能技术生成

问题

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

例子

在这里插入图片描述

思路

  • 方法1

  • 在这里插入图片描述
    在这里插入图片描述

    遍历链表数组,顺序取出链表和head合并

  • 方法2

  • 在这里插入图片描述

  • 在这里插入图片描述在这里插入图片描述

    归并分治的方法,一次合并2i和2i+1,并放在i下标【如果为奇数lists[len/2]=lists[len-1]】最后返回lists[0]

  • 方法 总共n个元素,k个链
    ** 逐一合并**
    2 n k + 3 n k + . . + k n k = n k × k 2 2 = O ( n k ) 2\frac{n}{k}+3\frac{n}{k}+..+k\frac{n}{k}=\frac{n}{k}\times\frac{k^2}{2}=O(nk) 2kn+3kn+..+kkn=kn×2k2=O(nk)
    两两合并
    第 一 次 合 并 : 2 n k ∗ k 2 = n 第一次合并:2\frac{n}{k}*\frac{k}{2}=n 2kn2k=n
    第 二 次 合 并 : 2 2 n k ∗ k 4 = n 第二次合并:2^2\frac{n}{k}*\frac{k}{4}=n 22kn4k=n
    第 l o g k 次 合 并 : 2 l o g k n k ∗ k k = n 第logk次合并:2^{logk}\frac{n}{k}*\frac{k}{k}=n logk2logkknkk=n
    时 间 复 杂 度 : O ( n l o g k ) 时间复杂度:O(nlogk) O(nlogk)
    优先队列,最小堆
    遍 历 n 次 , 每 次 调 整 时 间 l o g k − > O ( n l o g k ) 遍历n次,每次调整时间logk->O(nlogk) nlogk>O(nlogk)
    代码

  • 合并K个排序链表

//方法1 逐一合并 O(nk)
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        // ListNode head=null;
        // for(ListNode node:lists) {
        //     head=merge(head,node);
        // }
        // return head;

    }
    public ListNode merge(ListNode l1, ListNode l2) {
        if(l1==null) return l2;
        if(l2==null) return l1;
        
        if(l1.val<l2.val) {
            l1.next=merge(l1.next,l2);
            return l1;
        }
        l2.next=merge(l1,l2.next);
        return l2;
    }
}
//方法2 两两合并O(nlogk)
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        int len=lists.length;
        if(len==0) return null;
        while(len>1) {
            for(int i=0; i<len/2; i++) {
                lists[i]=merge(lists[2*i],lists[2*i+1]);
            }
            //如果lists总数是奇数个,则还剩一个
            if(len%2==1) {
                lists[len/2]=lists[len-1];
                len=len/2+1;//规模减半+1
            }else len=len/2;//规模减半
            
        }
            
        return lists[0];
    

    }
    public ListNode merge(ListNode l1, ListNode l2) {
        if(l1==null) return l2;
        if(l2==null) return l1;
        
        if(l1.val<l2.val) {
            l1.next=merge(l1.next,l2);
            return l1;
        }
        l2.next=merge(l1,l2.next);
        return l2;
    }
}
//优先队列,小顶堆 O(nlogk)
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length==0) return null;
        int k = lists.length;
        PriorityQueue<ListNode> q = new PriorityQueue<>((l1,l2)->l1.val-l2.val);
        for(int i=0; i<k; i++) {
            if(lists[i]==null) continue;//因为没有说每个链表的长度
            q.offer(lists[i]);
        }
        ListNode h = new ListNode(-1),cur=h;
        
        while(q.size()>0){
            ListNode node = q.poll();
            cur.next = node;
            cur=cur.next;
            if(node.next!=null) {
                q.offer(node.next);
            }
        }
        return h.next;
}
  • 合并k个数组,总元素为n个
//暴力,先合并,再排序 O(nlogn)
//逐一合并 O(nk)
//两两合并O(nlogk)
//不能使用优先队列,小顶堆,因为无法根据优先队列中的最小值获取其所在的数组及对应的下一个元素
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值