列表

详情


23. 合并K个升序链表

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

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

 

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

 

提示:

相似题目

合并两个有序链表

丑数 II

原站题解

去查看

上次编辑到这里,代码来自缓存 点击恢复默认模板
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists) { } };

java 解法, 执行用时: 4 ms, 内存消耗: 42.2 MB, 提交时间: 2023-08-12 08:57:28

/**
 * 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) {
        PriorityQueue<ListNode> pq = new PriorityQueue<>((a, b) -> a.val - b.val);
        for (ListNode head : lists)
            if (head != null)
                pq.offer(head);

        ListNode dummy = new ListNode(); // 哨兵节点,作为合并后链表头节点的前一个节点
        ListNode cur = dummy;
        while (!pq.isEmpty()) { // 循环直到堆为空
            ListNode node = pq.poll(); // 剩余节点中的最小节点
            if (node.next != null) // 下一个节点不为空
                pq.offer(node.next); // 下一个节点有可能是最小节点,入堆
            cur.next = node; // 合并到新链表中
            cur = cur.next; // 准备合并下一个节点
        }
        return dummy.next; // 哨兵节点的下一个节点就是新链表的头节点
    }
}

python3 解法, 执行用时: 76 ms, 内存消耗: 19.5 MB, 提交时间: 2023-08-12 08:57:03

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
ListNode.__lt__ = lambda a, b: a.val < b.val  # 让堆可以比较节点大小

class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        cur = dummy = ListNode()  # 哨兵节点,作为合并后链表头节点的前一个节点
        h = [head for head in lists if head]  # 初始把所有链表的头节点入堆
        heapify(h)  # 堆化
        while h:  # 循环直到堆为空
            node = heappop(h)  # 剩余节点中的最小节点
            if node.next:  # 下一个节点不为空
                heappush(h, node.next)  # 下一个节点有可能是最小节点,入堆
            cur.next = node  # 合并到新链表中
            cur = cur.next  # 准备合并下一个节点
        return dummy.next  # 哨兵节点的下一个节点就是新链表的头节点

golang 解法, 执行用时: 8 ms, 内存消耗: 5.4 MB, 提交时间: 2023-08-12 08:56:09

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeKLists(lists []*ListNode) *ListNode {
    h := hp{}
    for _, head := range lists {
        if head != nil {
            h = append(h, head)
        }
    }
    heap.Init(&h) // 堆化

    dummy := &ListNode{} // 哨兵节点,作为合并后链表头节点的前一个节点
    cur := dummy
    for len(h) > 0 { // 循环直到堆为空
        node := heap.Pop(&h).(*ListNode) // 剩余节点中的最小节点
        if node.Next != nil { // 下一个节点不为空
            heap.Push(&h, node.Next) // 下一个节点有可能是最小节点,入堆
        }
        cur.Next = node // 合并到新链表中
        cur = cur.Next // 准备合并下一个节点
    }
    return dummy.Next // 哨兵节点的下一个节点就是新链表的头节点
}

type hp []*ListNode
func (h hp) Len() int           { return len(h) }
func (h hp) Less(i, j int) bool { return h[i].Val < h[j].Val } // 最小堆
func (h hp) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
func (h *hp) Push(v any)        { *h = append(*h, v.(*ListNode)) }
func (h *hp) Pop() any          { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }

javascript 解法, 执行用时: 116 ms, 内存消耗: 47.8 MB, 提交时间: 2023-08-12 08:55:39

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function (lists) {
    let pq = new MinPriorityQueue({priority: e => e.val});
    for (const head of lists)
        if (head) pq.enqueue(head);

    let dummy = new ListNode(); // 哨兵节点,作为合并后链表头节点的前一个节点
    let cur = dummy;
    while (!pq.isEmpty()) { // 循环直到堆为空
        const node = pq.dequeue().element; // 剩余节点中的最小节点
        if (node.next) // 下一个节点不为空
            pq.enqueue(node.next); // 下一个节点有可能是最小节点,入堆
        cur.next = node; // 合并到新链表中
        cur = cur.next; // 准备合并下一个节点
    }
    return dummy.next; // 哨兵节点的下一个节点就是新链表的头节点
};

javascript 解法, 执行用时: 88 ms, 内存消耗: 46 MB, 提交时间: 2023-08-12 08:55:11

/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */

// 21. 合并两个有序链表
var mergeTwoLists = function (list1, list2) {
    let dummy = new ListNode(); // 用哨兵节点简化代码逻辑
    let cur = dummy; // cur 指向新链表的末尾
    while (list1 && list2) {
        if (list1.val < list2.val) {
            cur.next = list1; // 把 list1 加到新链表中
            list1 = list1.next;
        } else { // 注:相等的情况加哪个节点都是可以的
            cur.next = list2; // 把 list2 加到新链表中
            list2 = list2.next;
        }
        cur = cur.next;
    }
    cur.next = list1 ? list1 : list2; // 拼接剩余链表
    return dummy.next;
};

/**
 * @param {ListNode[]} lists
 * @return {ListNode}
 */
var mergeKLists = function (lists) {
    // 合并从 lists[i] 到 lists[j-1] 的链表
    function dfs(i, j) {
        const m = j - i;
        if (m === 0) return null; // 注意输入的 lists 可能是空的
        if (m === 1) return lists[i]; // 无需合并,直接返回
        const left = dfs(i, i + (m >> 1)); // 合并左半部分
        const right = dfs(i + (m >> 1), j); // 合并右半部分
        return mergeTwoLists(left, right); // 最后把左半和右半合并
    }
    return dfs(0, lists.length);
};

golang 解法, 执行用时: 4 ms, 内存消耗: 5 MB, 提交时间: 2023-08-12 08:54:20

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeTwoLists(list1, list2 *ListNode) *ListNode {
    dummy := &ListNode{} // 用哨兵节点简化代码逻辑
    cur := dummy         // cur 指向新链表的末尾
    for list1 != nil && list2 != nil {
        if list1.Val < list2.Val {
            cur.Next = list1 // 把 list1 加到新链表中
            list1 = list1.Next
        } else { // 注:相等的情况加哪个节点都是可以的
            cur.Next = list2 // 把 list2 加到新链表中
            list2 = list2.Next
        }
        cur = cur.Next
    }
    // 拼接剩余链表
    if list1 != nil {
        cur.Next = list1
    } else {
        cur.Next = list2
    }
    return dummy.Next
}

func mergeKLists(lists []*ListNode) *ListNode {
    m := len(lists)
    if m == 0 { // 注意输入的 lists 可能是空的
        return nil
    }
    if m == 1 { // 无需合并,直接返回
        return lists[0]
    }
    left := mergeKLists(lists[:m/2]) // 合并左半部分
    right := mergeKLists(lists[m/2:]) // 合并右半部分
    return mergeTwoLists(left, right) // 最后把左半和右半合并
}

cpp 解法, 执行用时: 136 ms, 内存消耗: 12.7 MB, 提交时间: 2023-08-12 08:52:41

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
        if ((!a) || (!b)) return a ? a : b;
        ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
        while (aPtr && bPtr) {
            if (aPtr->val < bPtr->val) {
                tail->next = aPtr; aPtr = aPtr->next;
            } else {
                tail->next = bPtr; bPtr = bPtr->next;
            }
            tail = tail->next;
        }
        tail->next = (aPtr ? aPtr : bPtr);
        return head.next;
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode *ans = nullptr;
        for (size_t i = 0; i < lists.size(); ++i) {
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }
};

java 解法, 执行用时: 99 ms, 内存消耗: 42.3 MB, 提交时间: 2023-08-12 08:52:09

/**
 * 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 ans = null;
        for (int i = 0; i < lists.length; ++i) {
            ans = mergeTwoLists(ans, lists[i]);
        }
        return ans;
    }

    public ListNode mergeTwoLists(ListNode a, ListNode b) {
        if (a == null || b == null) {
            return a != null ? a : b;
        }
        ListNode head = new ListNode(0);
        ListNode tail = head, aPtr = a, bPtr = b;
        while (aPtr != null && bPtr != null) {
            if (aPtr.val < bPtr.val) {
                tail.next = aPtr;
                aPtr = aPtr.next;
            } else {
                tail.next = bPtr;
                bPtr = bPtr.next;
            }
            tail = tail.next;
        }
        tail.next = (aPtr != null ? aPtr : bPtr);
        return head.next;
    }
}

java 解法, 执行用时: 1 ms, 内存消耗: 42.4 MB, 提交时间: 2023-08-12 08:48:14

/**
 * 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) {
        if (lists.length == 0) {
            return null;
        }
        return merge(lists, 0, lists.length - 1);
    }

    private ListNode merge(ListNode[] lists, int lo, int hi) {
        if (lo == hi) {
            return lists[lo];
        }
        int mid = lo + (hi - lo) / 2;
        ListNode l1 = merge(lists, lo, mid);
        ListNode l2 = merge(lists, mid + 1, hi);
        return merge2Lists(l1, l2);
    }
    
    private ListNode merge2Lists(ListNode l1, ListNode l2) {
        ListNode dummyHead = new ListNode(0);
        ListNode tail = dummyHead;
        while (l1 != null && l2 != null) {
            if (l1.val < l2.val) {
                tail.next = l1;
                l1 = l1.next;
            } else {
                tail.next = l2;
                l2 = l2.next;
            }
            tail = tail.next;
        }
    
        tail.next = l1 == null? l2: l1;
    
        return dummyHead.next;
    }
}

python3 解法, 执行用时: 64 ms, 内存消耗: 18.8 MB, 提交时间: 2022-08-30 11:45:22

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        if not lists:return 
        import heapq
        queue=[]
        for l in lists:#将lists的值放进小根堆
            head=l
            while head:
                heapq.heappush(queue,head.val)
                head=head.next
        dummy=ListNode(0)#构造虚拟节点
        cur=dummy
        while queue:#将堆顶取出连接成链表
            cur.next=ListNode(heapq.heappop(queue))
            cur=cur.next
        return dummy.next

python3 解法, 执行用时: 80 ms, 内存消耗: 26.8 MB, 提交时间: 2022-08-02 15:30:29

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        
        if not lists:return

        def merge2Lists(l1,l2):#两有序链表合并
            if not l1:return l2
            if not l2:return l1
            if l1.val<l2.val:
                l1.next=merge2Lists(l1.next,l2)
                return l1
            else:
                l2.next=merge2Lists(l1,l2.next)
                return  l2

        def helper(l,r):#二分法 使所有链表两两合并
            if l==r:return lists[l]
            n=len(lists)
            mid=(l+r)>>1
            l1=helper(l,mid)
            l2=helper(mid+1,r)
            return merge2Lists(l1,l2)

        return helper(0,len(lists)-1)

python3 解法, 执行用时: 64 ms, 内存消耗: 18.7 MB, 提交时间: 2022-08-02 15:29:59

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeKLists(self, lists: List[Optional[ListNode]]) -> Optional[ListNode]:
        nums=[]
        for l in lists:         #将所有列表的值取出来放进数组
            j=l
            while j:
                nums.append(j.val)
                j=j.next
        nums.sort()              #对数组排序
        dummy=ListNode(0)
        head=dummy
        for i in range(len(nums)):#将数组的值连接成链表
            head.next=ListNode(nums[i])
            head=head.next
        return dummy.next

上一题