Leetcode——合并K个升序链表
Posted Yawn,
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Leetcode——合并K个升序链表相关的知识,希望对你有一定的参考价值。
1. 题目
2. 题解
(1)逐一合并两条链表, 时间复杂度:O(NK)
时间复杂度:O(NK)
递归:
/**
* Definition for singly-linked list.
* 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; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode res = null;
for (ListNode list: lists) {
res = mergeTwoList(res, list);
}
return res;
}
//递归合并两个链表
public ListNode mergeTwoList(ListNode l1, ListNode l2){
if(l1 == null)
return l2;
if(l2 == null)
return l1;
if(l1.val < l2.val){
l1.next = mergeTwoList(l1.next, l2);
return l1;
}
l2.next = mergeTwoList(l1, l2.next);
return l2;
}
}
迭代:
/**
* Definition for singly-linked list.
* 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; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
ListNode res = null;
for (ListNode list: lists) {
res = mergeTwoList(res, list);
}
return res;
}
//迭代合并两个链表
public ListNode mergeTwoList(ListNode l1, ListNode l2){
ListNode newl = new ListNode(-1);
ListNode pre = newl;
while(l1 != null && l2 != null){
if(l1.val < l2.val){
pre.next = l1;
l1 = l1.next;
}else{
pre.next = l2;
l2 = l2.next;
}
pre = pre.next;
}
pre.next = (l1 == null ? l2 : l1);
return newl.next;
}
}
(2)K指针法
时间复杂度:O(NK)
/**
* Definition for singly-linked list.
* 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; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
int k = lists.length;
ListNode dummyHead = new ListNode(0); //哑节点
ListNode cur = dummyHead;
while (true) {
ListNode minNode = null; //最小头节点
int minPointer = -1; //最小头节点位置
for (int i = 0; i < k; i++) { //找到K条链表中最小的头节点
if (lists[i] == null) { //某一链表为空则跳过
continue;
}
if (minNode == null || lists[i].val < minNode.val) { //最小头结点为空(初始),或者当前头结点小于最小头结点时
minNode = lists[i];
minPointer = i;
}
}
if (minPointer == -1) { //所有节点为空,找不到节点时,退出循环
break;
}
cur.next = minNode; //结果节点脸上当前最小头节点,并向后移一位
cur = cur.next;
lists[minPointer] = lists[minPointer].next; //被取出头结点的链表,后移一位
}
return dummyHead.next;
}
}
(3)优先队列(小根堆优化)
时间复杂度:O(NlogK)
/**
* Definition for singly-linked list.
* 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; }
* }
*/
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
Queue<ListNode> pq = new PriorityQueue<>((v1, v2) -> v1.val - v2.val); //优先队列,小根堆
for (ListNode node: lists) { //将所有链表放入小根堆,根据头结点大小排序
if (node != null) {
pq.offer(node);
}
}
ListNode dummyHead = new ListNode(0);
ListNode tail = dummyHead;
while (!pq.isEmpty()) { //小根堆不为空时,堆顶即为最小头节点
ListNode minNode = pq.poll();
tail.next = minNode;
tail = minNode;
if (minNode.next != null) {
pq.offer(minNode.next); //更新当前被取出头结点
}
}
return dummyHead.next;
}
}
以上是关于Leetcode——合并K个升序链表的主要内容,如果未能解决你的问题,请参考以下文章
算法leetcode|23. 合并K个升序链表(rust重拳出击)