23-合并K个升序链表

这篇博客介绍了如何合并已排序的链表数组。通过两种方法实现:一是使用优先队列,二是采用递归策略。优先队列方法中,利用Java的PriorityQueue来找到最小的头节点并进行合并;递归方法则是将问题拆分为两半,逐个合并。最后给出了示例和详细的解题思路。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目

给你一个链表数组,每个链表都已经按升序排列。

请你将所有链表合并到一个升序链表中,返回合并后的链表。

示例 1:

输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2:

输入:lists = []
输出:[]

示例 3:

输入:lists = [[]]
输出:[]

题解一 优先队列

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length==0||lists==null){
            return null;
        }
        PriorityQueue<ListNode> queue=new PriorityQueue<>(lists.length,new Comparator<ListNode>(){
            public int compare(ListNode n1,ListNode n2){
                if(n1.val<n2.val){
                    return -1;
                }else if(n1.val==n2.val){
                    return 0;
                }else{
                    return 1;
                }
            }
        });//PriorityQueue(int initialCapacity, Comparator<? super E> comparator)使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器对元素进行排序。
        for(ListNode n:lists){//全部加入队列
            if(n!=null)queue.add(n);
        }
        //再一个个取出来放到答案里,答案记得加一个虚拟头节点,便于操作
        ListNode dummyHead=new ListNode(0);
        ListNode p=dummyHead;
        while(!queue.isEmpty()){
            p.next=queue.poll();//先得到p的下一个节点的内容,再将指针前移
            p=p.next;
            if(p.next!=null){//之前队列中只添加了链表的头!后面需要继续添加链表后面的部分!
                queue.add(p.next);
            }
        }
        return dummyHead.next;
    }
}

思路:

  1. 在一堆元素中找出前k个:优先队列!

  2. 头节点的作用:防止真实的头节点为空;便于节点的操作,统一了空表和非空表的操作。

  3. 优先队列:添加:add,查看并移除队首:poll,大小:size

    初始化:PriorityQueue() 使用默认的初始容量(11)创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。
    PriorityQueue(Collection<? extends E> c) 创建包含指定 collection 中元素的 PriorityQueue。
    PriorityQueue(int initialCapacity) 使用指定的初始容量创建一个 PriorityQueue,并根据其自然顺序对元素进行排序。
    PriorityQueue(int initialCapacity, Comparator<? super E> comparator) 使用指定的初始容量创建一个 PriorityQueue,并根据指定的比较器对元素进行排序。

题解二 递归

class Solution {
    public ListNode mergeKLists(ListNode[] lists) {
        if(lists.length==0){
            return null;
        }
        if(lists.length==1){
            return lists[0];
        }
        if(lists.length==2){
            return mergeTwoLists(lists[0],lists[1]);
        }
        int len=lists.length/2;
        ListNode[] l1=new ListNode[len];
        ListNode[] l2=new ListNode[lists.length-len];
        for(int i=0;i<len;i++){
            l1[i]=lists[i];
        }
        for(int i=0,j=len;j<lists.length;i++,j++){
            l2[i]=lists[j];
        }
        return mergeTwoLists(mergeKLists(l1),mergeKLists(l2));
    }
    private ListNode mergeTwoLists(ListNode node1,ListNode node2){
        if(node1==null){
            return node2;
        }
        if(node2==null){
            return node1;
        }
        ListNode dummyHead=new ListNode(0);
        if(node1.val<=node2.val){
            dummyHead.next=node1;
            node1.next=mergeTwoLists(node1.next,node2);//node1的下一个原本指向本链表的下一个,这样的递归使其指向
        }else{
            dummyHead.next=node2;
            node2.next=mergeTwoLists(node1,node2.next);
        }
        return dummyHead.next;
    }
}

思路:

  1. 合并两个lists的思路和21是一样的。先写终止条件,再设置虚拟头节点,比较两个节点的大小,小节点的下一个指针指向整个递归体。
  2. 再将整个数组分成两半,递归调用merge函数。
  3. 注意在主函数返回时mergeTwoLists中,要调用主函数。多看看这种题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

codrab

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值