惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hugging Face - Blog
Hugging Face - Blog
GbyAI
GbyAI
Engineering at Meta
Engineering at Meta
有赞技术团队
有赞技术团队
博客园 - 【当耐特】
H
Hackread – Cybersecurity News, Data Breaches, AI and More
WordPress大学
WordPress大学
博客园_首页
美团技术团队
H
Help Net Security
MongoDB | Blog
MongoDB | Blog
宝玉的分享
宝玉的分享
大猫的无限游戏
大猫的无限游戏
小众软件
小众软件
J
Java Code Geeks
A
About on SuperTechFans
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
IT之家
IT之家
T
The Blog of Author Tim Ferriss
Microsoft Azure Blog
Microsoft Azure Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
B
Blog
雷峰网
雷峰网
爱范儿
爱范儿

博客园 - 有点懒惰的大青年

shell脚本变量记录 Python格式化字符串 Python中的浅拷贝和深拷贝 CompletableFuture.runAsync来进行异步任务和ThreadPoolExecutor来执行有什么区别? 用一个实际业务场景演示ON和WHERE的正确使用方式 idea中查看源码 异或运算 使用Hutool对时间的花式操作 比较器 枚举类的设计模式 spring boot中使用RedissonClient实现分布式锁 idea同时启动application,启用不同端口 @PostConstruct用法 ApplicationContext 事件发布与监听机制详解 java自带命令jps介绍 关于maven中标签的说明 mysql的跨库查询 linux命令ll显示结果的含义 Files类的使用 java环境变量设置 java值传递和引用传递 kafka的集群与可靠性 kafka的消费全流程 关于kafka 达梦数据库执行计划介绍 关于MQ 用位运算实现加减乘除(3)
合并K个升序列表
有点懒惰的大青年 · 2026-03-19 · via 博客园 - 有点懒惰的大青年

题目:给你多条链表,举个例子,如下三条链表:

1->2->6->7

2->4->4->5

3->7->7->9

你给我合成一个大链表,每一条链表都有序,请你合成一个总的有序的链表,结果应该是:

1->2->2->3->4->4->5->6->7->7->7->9

并返回第1个节点。

image

图1:

image

图2:

image

图3:

image

图4:

image

思路:

1.先把每个链表的头节点放进去,放进去后天然就排好序,根据节点的值。但是每个头节点的指针还是各自指着各自的下一个节点。

2.弹出一个节点,1被弹出,是最小的节点,就是head。1的下个节点4进去,因为是小根堆有序会自己调整,4就会插在2和5之间。

3.小根堆再弹出个节点2,2的下个节点3进去,3在顶部,小根堆里面现在是3,4,5。2放在步骤2弹出的节点1后面。

4.再将3弹出来,7进去,7在4和5后面。弹出来的3放在步骤3中2节点后面。

5.周而复始,直到小根堆中的所有元素都弹出。

代码如下:

package com.cy.class06;

import java.util.Comparator;
import java.util.PriorityQueue;

public class Code01_MergeKSortedLists {

    public static class ListNode {
        public int val;
        public ListNode next;
    }

    public static class ListNodeComparator implements Comparator<ListNode> {

        @Override
        public int compare(ListNode o1, ListNode o2) {
            return o1.val - o2.val;
        }
    }

    /**
     * 为什么入参是数组,lists里面n个元素,每个元素都是一个链表,而传进来的是n个链表各自的头节点。
     * 怎么估算这个方法的复杂度?
     *
     */
    public static ListNode mergeKLists(ListNode[] lists) {
        if (lists == null || lists.length == 0) {
            return null;
        }
        PriorityQueue<ListNode> heap = new PriorityQueue<>(new ListNodeComparator());

        //先把所有的头节点添加进小根堆
        for (int i = 0; i < lists.length; i++) {
            if (lists[i] != null) {
                heap.add(lists[i]);
            }
        }
        if (heap.isEmpty()) {
            return null;
        }

        ListNode head = heap.poll();
        ListNode pre = head;
        if (pre.next != null) {
            heap.add(pre.next);
        }
        while (!heap.isEmpty()) {
            ListNode cur = heap.poll();
            pre.next = cur;
            pre = cur;
            if (cur.next != null) {
                heap.add(cur.next);
            }
        }
        return head;
    }
}

如何估算这个算法的复杂度?

假设一共m条链表,m条链表的总节点数假设是n,小根堆因为是出来一个进去一个,所以小根堆的大小不会超过m,有关小根堆的所有操作o(logm)的复杂度。一共n个节点出去进来,一共操作n次,复杂度为:o(N * logm)

--