算法修炼之路——【链表】Leetcode 23 合并K个有序链表

题目描述

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

示例1:

输入: lists = {listA, listB, listC}, listA= [1, 4, 5], listB = [1, 3, 4], listC = [2, 6]
输出: [1, 1, 2, 3, 4, 4, 5, 6]

思路分析

这道题目为困难难度,这道题和多路归并排序方法思路很像,核心思想是分而治之。我们在Leetcode21已知如何对两个排序链表进行合并,这里K个有序链表可通过两两合并的方式进行排序,这里我们给出示意图:
在这里插入图片描述
图1
如图1所示,我们在第一次两两排序时,间隔为1:{0,1; 2,3};第二次两两排序时,间隔为3:{0,3},易推断,间隔interval初始值应为1,之后更新为2 * interval, interval = interval*2.

这里我们还需要注意,当输入的链表矩阵长度为奇数时,最后一项会在最终结果的前一次两两排序时参与到运算中。

解题步骤

  1. 初始化间隔整型变量interval,并求取输入矩阵长度len
  2. 遍历链表矩阵,并在每次遍历后更新一对排序链表中的下表较小的链表指针,同时更新interval = 2*interval
  3. 返回链表矩阵的首元素lists[0]

解题代码

    public static ListNode solution(ListNode[] lists) {
        if(lists == null) return null;
        if(lists.length == 1) return lists[0];
        
        /* Step1: Init  */
        int interval = 1;       
        int len = lists.length;
        
        /* Step2: go through the head-list
        and
        compare joint listnode in array-lists
         */        
        for (int i = 0; i < len; i = i + interval*2) {
            for(int j = 0; j < len-interval; j=j+interval){
                lists[j] = sortTwoSortedList(lists[j], lists[j + interval]);
            }
            interval *= 2;                        
        }

        return lists[0];

    }

    private static ListNode sortTwoSortedList(ListNode listA, ListNode listB) {
        if (listA == null) {
            return listB;
        }
        if (listB == null) {
            return listA;
        }

        /* Step1: Init. pointers */
        ListNode dummyHead = new ListNode(0);
        ListNode pA = listA;
        ListNode pB = listB;
        ListNode tmpTail = dummyHead;

        /* Step2: go through the head-list
        and
        compare pA.next.val and pB.val
         */
        while (pA != null && pB != null) {
            if (pA.val < pB.val) {
                tmpTail.next = pA;
                pA = pA.next;
            } else {
                tmpTail.next = pB;
                pB = pB.next;
            }
            tmpTail = tmpTail.next;
        }

        // Step3: connect subsequent if exists
        tmpTail.next = pA == null ? pB : pA;
        /* Step4: return  */
        return dummyHead.next;
    }

复杂度分析

已知链表矩阵的长度分别为k(即链表个数),链表长度可设为N

时间复杂度:代码中我们存在for循环的嵌套,且两两交换的时间复杂度为O(N);我们对链表矩阵进行了分治解法(第一层for循环时间复杂度为O(logk)),故时间复杂度即为O(Nlogk);
空间复杂度:我们这里没有设置辅助容器,故空间复杂度为O(1).

GitHub源码

完整可运行文件请访问GitHub

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值