Skip to main content

23.合并K个排序链表

标签: linked-list, divide-and-conquer, heap

难度: Hard

通过率: 55.03%

原题链接: https://leetcode.com/problems/merge-k-sorted-lists/description/

题目描述

给定一个由k个已排序链表组成的数组,将所有链表合并为一个排序链表,返回合并后的链表。

解题思路

这个问题要求我们将多个已排序的链表合并成一个整体已排序的链表。可以使用以下几种方法来解决:

  1. 逐步合并:使用一个循环,两两合并链表。这种方法简单直观,但效率不高,时间复杂度为O(kn)O(k \cdot n),其中kk是链表的数量,nn是每个链表的平均长度。

  2. 优先级队列(小顶堆)

    • 初始化一个优先级队列(或小顶堆),将每个链表的首节点入队。
    • 从堆中提取最小节点,然后将这个节点的next节点(如果有的话)入队。
    • 重复这个过程,直到堆为空。
    • 这种方法在每次选择节点的时候只选择堆顶节点,所以合并的时间复杂度为O(nlogk)O(n \log k),其中nn是链表中节点的总数。
  3. 分治

    • 类似于归并排序的思想,可以采用分治法。
    • 将k个链表进行两两合并,先合并相邻的链表,继续递归直到合并成一个完整的链表。
    • 这种方法的时间复杂度是O(nlogk)O(n \log k),空间复杂度为O(1)O(1)

代码实现

# Python 版本
import heapq

class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next

class Solution:
def mergeKLists(self, lists):
# 定义一个优先级队列
heap = []
# 初始化优先级队列,将每个链表的首节点入队
for i, ln in enumerate(lists):
if ln:
heapq.heappush(heap, (ln.val, i, ln))
# 创建一个哑节点来构建返回的链表
dummy = ListNode()
current = dummy
# 从优先级队列中逐个取出最小节点构建新的链表
while heap:
val, i, node = heapq.heappop(heap)
current.next = node
current = current.next
if node.next:
heapq.heappush(heap, (node.next.val, i, node.next))
# 返回合并后的链表
return dummy.next

复杂度分析

时间复杂度:

使用优先级队列的小顶堆方法,时间复杂度为 O(nlogk)O(n \log k),其中kk是链表的数量,nn是所有节点的总数。

空间复杂度:

优先级队列最多包含kk个元素,因此空间复杂度为 O(k)O(k)