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重拳出击)

Leetcode23. 合并K个升序链表(优先队列)

LeetCode 23 合并K个升序链表

LeetCode 23 合并K个升序链表

Python描述 LeetCode 23. 合并K个升序链表

302.LeetCode | 23. 合并K个升序链表