合并 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个升序链表结束

相关推荐
wheeldown7 小时前
【数据结构】选择排序
数据结构·算法·排序算法
躺不平的理查德11 小时前
数据结构-链表【chapter1】【c语言版】
c语言·开发语言·数据结构·链表·visual studio
阿洵Rain11 小时前
【C++】哈希
数据结构·c++·算法·list·哈希算法
Leo.yuan11 小时前
39页PDF | 华为数据架构建设交流材料(限免下载)
数据结构·华为
半夜不咋不困12 小时前
单链表OJ题(3):合并两个有序链表、链表分割、链表的回文结构
数据结构·链表
忘梓.12 小时前
排序的秘密(1)——排序简介以及插入排序
数据结构·c++·算法·排序算法
y_m_h15 小时前
leetcode912.排序数组的题解
数据结构·算法
1 9 J15 小时前
数据结构 C/C++(实验三:队列)
c语言·数据结构·c++·算法
921正在学习编程15 小时前
数据结构之二叉树前序,中序,后序习题分析(递归图)
c语言·数据结构·算法·二叉树
毕竟秋山澪15 小时前
岛屿数量 广搜版BFS C#
数据结构·算法·宽度优先