牛客网刷题-合并k个已排序的链表

问题描述

合并 k 个已排序的链表并将其作为一个已排序的链表返回。分析并描述其复杂度。

输入描述:
输入一个链表的集合

输出描述:
输出合并后的链表

示例

示例1

输入
[{1,2,3},{4,5,6,7}]

输出
{1,2,3,4,5,6,7}

解决思路

分析

  1. 通过顺序合并的方式,先合并前两个链表,然后以合并后的链表一次与后面每一个链表合并(这种方式会花费额外的时间,这里不做介绍)
  2. 通过二分分组的方式,对链表分组,分 k/2 组,对每组的两个链表进行合并,取合并后的链表再进行分组,重复这个过程
  3. 通过优先队列的方式,通过维护每个链表的首元素,依次弹出追加元素(后期会补充代码)

方法

  1. 通过对链表进行二分分组的方式实现排序

代码实现

// 思路1
public class Solution {
    
      
    public ListNode merge(ArrayList<ListNode> lists, int l, int r) {
    
    
        if (l == r) {
    
    
            return lists.get(l);
        }
        if (l > r) {
    
    
            return null;
        }
        int mid = (l + r) >> 1;
        return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
    }

    private ListNode mergeTwoLists(ListNode l1, ListNode l2) {
    
    
        if (l1 == null || l2 == null) {
    
    
            return l1 == null ? l2 : l1;
        }

        ListNode dummy = new ListNode(0);
        ListNode temp = dummy;
        while (l1 != null && l2 != null) {
    
    
            if (l1.val < l2.val) {
    
    
                temp.next = l1;
                l1 = l1.next;
            } else {
    
    
                temp.next = l2;
                l2 = l2.next;
            }
            temp = temp.next;
        }

        if (l1 != null) temp.next = l1;
        if (l2 != null) temp.next = l2;

        return dummy.next;
    }
}

时间复杂度分析:
第一次分组:k/2个组,每组合并需要的时间复杂度为2个链表的长度和,假设最长为n,则每组合并的时间复杂度为O(2n),总的时间复杂度为:O(k/2 * 2n) = O(kn)
第二次分组:k/4个组,每组合并需要的时间复杂度为4个链表的长度和 O(4n) 【注意:这里承接了第一组,所以长度会*2】,总的时间复杂度为:O(k/4 * 4n) = O(kn)
第logk次分区,相同,因为采用了二分的方法分组,所以k组分组的总共次数为logk次,所以总的时间复杂度为O(logk * kn)

空间复杂度分析:
因为采用递归的方式,没有申请额外的空间存储,所以空间复杂度为O(1)

小伙伴如果想测试的话,可以直接到牛客网这个链接做测试

合并k个已排序的链表-牛客网

猜你喜欢

转载自blog.csdn.net/qq_35398517/article/details/113486963
今日推荐