leetcode23-合并K个升序链表

1.问题描述

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

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

示例 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 = [[]]
输出:[]

提示:

k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i] 按 升序 排列
lists[i].length 的总和不超过 10^4

解题思路:

本题有多种解题思路。
如顺序合并,即最朴素的方法:用一个变量 ans 来维护以及合并的链表,第 ii 次循环把第 ii 个链表和 ans 合并,答案保存到 ans 中。使用到了两两归并的过程,但是时间复杂度会达到O(k2n)
还有一种是使用分治算法,但过程较为复杂
本文仅介绍一种时间复杂度较优,且实现非常容易的算法,即借助Java的优先级队列,Java优先级队列的具体介绍请参看:Java优先级队列PriorityQueue将K个链表中的所有结点全部入队,然后每次从队列中取出队头元素,即队列中的最小元素使用尾插法插入到虚拟头结点的后面。最终就可以将原K个链表按照从小到大的顺序排序。时间复杂度O(nlogn),但空间复杂度也为O(n)

实现代码:

class Solution {
    
    
    public ListNode mergeKLists(ListNode[] lists) {
    
    
        //创建优先级队列,传入一个比较器,比较器和优先级队列的参数都是ListNode
        Queue<ListNode> pqueue=new PriorityQueue<ListNode>(new Comparator<ListNode>(){
    
    
			@Override
            //实现Comparator接口的compare方法。两个listNode排序时按照val值
			public int compare(ListNode o1, ListNode o2) {
    
    
				return o1.val-o2.val;
			}
			
		});
        //遍历K个升序链表,将其全部加入到优先级队列中
        for(ListNode li:lists){
    
    
            ListNode p=li;
            while(p!=null){
    
    
                pqueue.offer(p);
                p=p.next;
            }
        }
        ListNode head=new ListNode(-1);     //创建虚拟头结点
        //我们使用的尾插法,尾插法能够保证元素按照插顺序进行组织,所以要维护一个尾结点    
        ListNode r=head;    
        //每次将优先级队列中的队头元素取出,加入到链表中                
        while(!pqueue.isEmpty()){
    
    
            ListNode p=pqueue.poll();
            r.next=p;
            r=r.next;
        }
        //最终一定要将r.next置为空,否则可能会发生错误
        r.next=null;
        return head.next;       //返回虚拟头结点的next指针。
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39736597/article/details/113833043