合并 K 个升序链表

合并2个升序链表

首先想要合并k个升序链表要先明白如何合并2个升序链表

链表节点的结构为:

java 复制代码
public class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val; this.next = next; }
}

循环判断两个链表的值大小关系,将小的那个赋值到新创建链表节点的下一个,循环结束后其中一个链表可能还未全部遍历,将其赋值在当前节点的next即可。

java 复制代码
class Solution {
    public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
        //创建头节点和临时节点,头节点用于返回结果,临时节点用于不断给下一个赋值
        ListNode newList = new ListNode();
        ListNode tmp = newList;

        while(list1 != null && list2 != null) {
            if(list1.val <= list2.val){    //如果第一个列表的当前值小于等于第二个列表的当前值
                tmp.next = list1;          //将第一个列表的的当前节点赋值到临时节点的下一个
                list1 = list1.next;        //移动到下一个
            }else{                         //第二个列表当前值小于第一个列表当前值
                tmp.next = list2;          //将第二个列表的的当前节点赋值到临时节点的下一个
                list2 = list2.next;
            }
            tmp = tmp.next;                //临时节点移动到下一个
        }

        //使用三木运算符判断某个列表是否还未循环结束,若有赋值到临时节点的下一个即可
        tmp.next = list1 != null ? list1 : list2;
        //返回头的下一个即可
        return newList.next;
    }
}

分治法

分治思想:

将多个数据,先进行对半拆分,分到都剩最后一个链表时返回当前链表,在将两个链表进行合并排序。

到最后全部拆分的链表合并为一个时,结束算法。

合并 K 个升序链表

使用分治法,先对半拆分,将k个链表分成左半部分和右半部分,直到结束条件(当前只剩一条链表)时返回当前链表。

设计一个方法sort,分别需要参数总链表lists,左边索引值start和右边索引值end。当左边索引等于右边索引时,返回lists[start]

此时左半部分和右半部分会返回一条升序的链表,为左半部分升序链表(后面都称为左链)和右半部分升序链表(后面都称为右链),使用合并两个升序链表合并思想将左链和右链合并为一条升序链表,返回当前升序链表。

进行多次的拆分和合并递归后最终由k个升序链表得到一条升序链表。

java 复制代码
class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) return null;//当前列表为空或长度为0返回null
        return sort(lists, 0, lists.length - 1);
    }

    public ListNode sort(ListNode[] lists, int start, int end) {
        if (start == end)                           //结束条件,即只剩一条链表时返回
            return lists[start];

        int i = (end + start) / 2;                  //根据左右两个索引获得中间索引值
        ListNode left = sort(lists, start, i);      //拆分为left和right部分
        ListNode right = sort(lists, i + 1, end);   //此时两个返回值都是一条升序链表

        ListNode head = new ListNode(), tem = head; //设置头节点
                                                    //后续代码和合并2条有序链表代码相同
        while(left != null && right != null) {
            if (left.val <= right.val){
                tem.next = left;
                left = left.next;
            }
            else{
                tem.next = right;
                right = right.next;
            }
            tem = tem.next;
        }

        if(left != null)
            tem.next = left;
        if(right != null)
            tem.next = right;

        return head.next;
    }
}

至此合并k个升序链表结束

相关推荐
Tingjct2 小时前
【初阶数据结构-二叉树】
c语言·开发语言·数据结构·算法
C雨后彩虹2 小时前
计算疫情扩散时间
java·数据结构·算法·华为·面试
飞机和胖和黄3 小时前
考研之王道C语言第三周
c语言·数据结构·考研
达文汐3 小时前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
一匹电信狗3 小时前
【LeetCode_21】合并两个有序链表
c语言·开发语言·数据结构·c++·算法·leetcode·stl
执着2593 小时前
力扣hot100 - 234、回文链表
算法·leetcode·链表
Gorgous—l3 小时前
数据结构算法学习:LeetCode热题100-多维动态规划篇(不同路径、最小路径和、最长回文子串、最长公共子序列、编辑距离)
数据结构·学习·算法
一条大祥脚4 小时前
26.1.26 扫描线+数论|因子反演+子序列计数|树套树优化最短路
数据结构·算法
踩坑记录5 小时前
leetcode hot100 23. 合并 K 个升序链表 hard 分治 迭代
leetcode·链表
李老师讲编程5 小时前
C++信息学奥赛练习题-杨辉三角
数据结构·c++·算法·青少年编程·信息学奥赛