合并 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。当左边索引等于右边索引时,返回listsstart

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

进行多次的拆分和合并递归后最终由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个升序链表结束

相关推荐
乐观勇敢坚强的老彭13 小时前
C++信奥静态数组和动态数组
数据结构·c++·算法
旖旎夜光14 小时前
LeetCode 991: 坏了的计算器(贪心算法) —— 题解
数据结构·c++·算法·leetcode·贪心算法
旖旎夜光14 小时前
LeetCode 553:最优除法(贪心算法) —— 题解
数据结构·c++·算法·leetcode·贪心算法
雾喔14 小时前
算法练习7
java·数据结构·算法
XiaoYu1__17 小时前
数据结构进阶·其二:用简洁的树状数组处理动态区间问题及两种常见变形
数据结构·c++·笔记·算法·树状数组
Keven_1117 小时前
算法札记:二叉树前序、中序、后序遍历及对应序列重要性质
数据结构·算法·深度优先
如此这般英俊17 小时前
手搓Claude Code-第十章 system_prompt
数据结构·人工智能·python·语言模型·自然语言处理·prompt
旖旎夜光18 小时前
LeetCode 435:无重叠区间(贪心算法) —— 题解
数据结构·c++·算法·leetcode·贪心算法
旖旎夜光18 小时前
LeetCode 738:单调递增的数字(贪心算法) —— 题解
数据结构·c++·算法·leetcode·贪心算法
旖旎夜光18 小时前
LeetCode 1262:可被三整除的最大和 (贪心算法)—— 题解
数据结构·c++·算法·leetcode·贪心算法