算法-堆、队列、分治法-合并 K 个升序链表

news2024/12/26 1:15:32

算法-堆、队列、分治法-合并 K 个升序链表

1 题目概述

1.1 题目出处

https://leetcode.cn/problems/merge-k-sorted-lists

1.2 题目描述

在这里插入图片描述

2 题解

2.1 队列

2.1.1 解题思路

将各个有序子链表放入队列,两两合并,最后队列中剩的最后的子链表就是合并后的结果。

2.1.2 代码

/**
 * 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;
        }
        Queue<ListNode> queue = new LinkedList<>();
        for(ListNode node : lists) {
            if (node != null) {
                queue.add(node);
            }
        }
        while (queue.size() > 1) {
            ListNode left = queue.poll();
            ListNode right = queue.poll();
            queue.add(mergeKLists(left, right));
        }
        
        return queue.poll();
    }
    private ListNode mergeKLists(ListNode left, ListNode right) {
        ListNode head = new ListNode();
        ListNode tmpH = head;
        ListNode tmpL = left;
        ListNode tmpR = right;
        while (tmpL != null && tmpR != null) {
            if (tmpL.val < tmpR.val) {
                tmpH.next = tmpL;
                tmpL = tmpL.next;
            } else {
                tmpH.next = tmpR;
                tmpR = tmpR.next;
            }
            tmpH = tmpH.next;
        }
        if (tmpL == null) {
            tmpH.next = tmpR;   
        }
        if (tmpR == null) {
            tmpH.next = tmpL;   
        }
        return head.next;
    }
}

2.1.3 时间复杂度

参考 https://leetcode.cn/problems/merge-k-sorted-lists/solutions/219756/he-bing-kge-pai-xu-lian-biao-by-leetcode-solutio-2/?envType=study-plan-v2&envId=top-interview-150
在这里插入图片描述

2.1.4 空间复杂度

O(log⁡k)
递归会使用到 O(log⁡k)空间代价的栈空间。

2.2 堆-由优先级队列实现

2.2.1 解题思路

  1. 将所有元素一次插入小顶堆
  2. 将小顶堆的所有元素依次取出并组成链表
  3. 最后得到的链表就是从小到大排列的链表

2.2.2 代码

/**
 * 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 head = new ListNode();
        if (lists.length == 0) {
            return null;
        }

        PriorityQueue<ListNode> queue = new PriorityQueue<>((o1, o2) -> {
            return o1.val - o2.val;
        });

        for (ListNode listNode : lists) {
            if (null == listNode) {
                continue;
            }
            ListNode tmp = listNode;
            while (null != tmp) {
                queue.add(tmp);
                tmp = tmp.next;
            }
        }
        ListNode tmp = queue.poll();
        head.next = tmp;
        while (queue.size() > 0) {
            tmp.next = queue.poll();
            tmp = tmp.next;
        }
        if (null != tmp) {
            tmp.next = null;
        }
        
        return head.next;
    }
}

2.2.3 时间复杂度

O(NKlogNK)

2.2.4 空间复杂度

O(NK)

2.3 堆-由自己实现堆-优化

2.2.1 解题思路

  1. 将K个队列的元素每次都拿1个插入小顶堆,组成一个大小为K的小顶堆
  2. 每次将小顶堆的堆顶元素取出,并将该元素的下一个元素放入小顶堆
  3. 最后得到的链表就是从小到大排列的链表

2.2.2 代码

/**
 * 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; }
 * }
 */
/**
 * 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 {
    private class MinHeap {
        private List<ListNode> list = new ArrayList<>();
        public void add(ListNode node) {
            // 添加时,先把node放到小顶堆尾
            list.add(node);
            int i = list.size() - 1;
            ListNode tmp = node;
            while (i > 0) {
                // 每次和父节点对比,
                // 这是小顶堆,则如果当前节点比父节点更小,就和父节点交还位置
                int parent = (i - 1) / 2;
                if (tmp.val < list.get(parent).val) {
                    list.set(i, list.get(parent));  
                    i = parent;
                } else {
                    break;
                }
            }
            // 最后i的位置就是合适位置了,将目标节点放入即可
            list.set(i, tmp);
        }
        public ListNode poll() {
            if (size() == 0) {
                return null;
            }
            // 小顶堆取节点时,直接取首节点即val最小的节点
            ListNode target = list.get(0);
            if (size() == 1) {
                list.remove(0);
                return target;
            }
            // 将堆顶节点和尾节点交换位置,并从上至下开始调整堆
            list.set(0, list.get(size() - 1));
            list.remove(size() - 1);
            int i = 0;
            ListNode tmp = list.get(0);
            while ((i * 2 + 1) < size()) {
                int child = i * 2 + 1;
                if (child < list.size() - 1 && list.get(child).val > list.get(child + 1).val) {
                    child = child + 1;
                }
                if (tmp.val > list.get(child).val) {
                    list.set(i, list.get(child));
                    i = child;
                } else {
                    break;
                }
            }
            list.set(i, tmp);
            return target;
        }
        public int size() {
            return list.size();
        }
    }
    public ListNode mergeKLists(ListNode[] lists) {       
        if (lists.length == 0) {
            return null;
        }
        MinHeap heap = new MinHeap();
        for(ListNode node : lists) {
            if (node != null) {
                heap.add(node);
            }
        }
        ListNode dummpy = new ListNode();
        ListNode tail = dummpy;
        while (heap.size() > 0) {
            ListNode node = heap.poll();
            tail.next = node;
            tail = node;
            if (null != node.next) {
                heap.add(node.next);
            }
        }
        
        return dummpy.next;
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1038141.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【湖科大教书匠】计算机网络随堂笔记第3章(计算机网络数据链路层)

目录 3.1、数据链路层概述 概述 网络中的主机、路由器等都必须实现数据链路层 局域网中的主机、交换机等都必须实现数据链路层 从层次上来看数据的流动 仅从数据链路层观察帧的流动 数据链路层使用的信道 三个重要问题 封装成帧 差错控制 ​编辑可靠传输 3.2、封装成帧 介绍…

Redis客户端

文章目录 一、scan命令二、数据库管理命令三、RESP协议四、string类型五、list类型六、set类型七、hash类型八、zset类型 一、scan命令 keys是一次性把整个redis中所有的key都获取道&#xff0c;这个操作比较危险&#xff0c;可能会一下子得到大量的key&#xff0c;阻塞redis服…

009_第一代软件开发(一)

第一代软件开发(一) 文章目录 第一代软件开发(一)项目介绍借鉴前辈UI传统QWidget OR QML建立远程仓库&#xff0c;并拉取至本地 关键字&#xff1a; Qt、 Qml、 git、 版本控制、 关键字5 项目介绍 欢迎来到我们的 QML & C 项目&#xff01;这个项目结合了 QML&#x…

设计模式再探——原型模式

目录 一、背景介绍二、思路&方案三、过程1.原型模式简介2.原型模式的类图3.原型模式代码4.原型模式深度剖析5.原型模式与spring 四、总结五、升华 一、背景介绍 最近在做业务实现的时候&#xff0c;为了通过提升机器来降低开发人员的难度和要求&#xff0c;于是在架构设计…

RabbitMQ - 消息堆积问题的最佳解决方案?惰性队列

目录 一、惰性队列 1.1、消息堆积问题 1.2、消息堆积问题的解决方法 从消费者的角度&#xff1a; 从队列的角度&#xff1a; 1.3、引入惰性队列 1.3.1、什么是惰性队列 1.3.2、惰性队列的使用 1.3.3、效果演示 一、惰性队列 1.1、消息堆积问题 当生产者发送消息的速度…

leetcodeTop100(21) 相交链表

给你两个单链表的头节点 headA 和 headB &#xff0c;请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点&#xff0c;返回 null 。 题目数据 保证 整个链式结构中不存在环。 注意&#xff0c;函数返回结果后&#xff0c;链表必须 保持其原始结构 。 双链表…

1:DDD入门

产品代码都给你看了&#xff0c;可别再说不会DDD&#xff08;一&#xff09;&#xff1a;DDD入门 # 这是一个讲解DDD落地的文章系列&#xff0c;作者是《实现领域驱动设计》的译者滕云。本文章系列以一个真实的并已成功上线的软件项目——码如云&#xff08;https://www.mryqr…

【车载开发系列】UDS中Bootloader实现原理

【车载开发系列】UDS中Bootloader实现原理 【车载开发系列】UDS中Bootloader实现原理 【车载开发系列】UDS中Bootloader实现原理一. Bootloader存放位置二. BootLoader的安全机制1&#xff09;安全访问2&#xff09;刷新预条件3&#xff09;完整性校验4&#xff09;一致性检查5…

NextJS 引入 Ant-Design 样式闪烁问题

按照这里给的样例&#xff0c;抽出关键代码即可 步骤&#xff1a; 安装包&#xff1a; npm i ant-design/static-style-extract引入这俩文件 genAntdCss.tsx: 会帮我们生成 ./public/antd.min.css // src/scripts/genAntdCss.tsximport { extractStyle } from "ant-d…

从锁的类别角度讲,MySQL都有哪些锁

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;CSDN领军人物&#xff0c;全栈领域优质创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师…

2024北京老博会,CBIAIE中国北京国际老年产业博览会

2024第11届中国&#xff08;北京&#xff09;国际老年产业博览会&#xff0c;将于4月10-12日盛大举行 2024第11届中国&#xff08;北京&#xff09;国际老年产业博览会&#xff08;CBIAIE北京老博会&#xff09; The 2024 eleventh China (Beijing) International Aged Indust…

【动手学深度学习-Pytorch版】长短期记忆网络LSTM

LSTM参数说明以及网络架构图 PS&#xff1a;时间仓促&#xff0c;有空补充内容~ LSTM从零开始实现 """ 遗忘门&#xff1a;相当于一个橡皮擦&#xff0c;决定保留昨天的哪些信息 输入门&#xff1a;相当于一个铅笔&#xff0c;再次根据昨天的记忆和今天的输…

【数据结构】list.h 详细使用教程 -- 附带例子代码

目录 一、概述二、详细使用步骤✨2.1 定义结构体包含 struct list_head 成员✨2.2 初始化链表头结点&#xff1a;INIT_LIST_HEAD✨2.3 添加结点&#xff1a;list_add、list_add_tail✨2.4 遍历链表&#xff1a;list_for_each、list_for_each_safe、list_for_each_entry✨2.5 获…

java double类型 向上取整,向下取整,四舍五入

向上取整&#xff1a;Math.ceil(double a) 向下取整&#xff1a;Math.floor(double a) 四舍五入取整&#xff1a;Math.round(double a) 直接取整数&#xff1a;intValue() public static void main(String[] args) {Double number 5.3;Double number1 5.8;//向上取整Doubl…

UE5 虚幻引擎 如何使用构造脚本(Construction Script)? 构造脚本的奥秘!

目录 1 构造脚本&#xff08;Construction Script&#xff09;1.1 介绍1.2 案例1&#xff1a;利用样条组件程序化生成树木1.2 案例2&#xff1a;利用样条组件和样条网格体组件程序化生成道路 1 构造脚本&#xff08;Construction Script&#xff09; 1.1 介绍 问题&#xff1a…

leetcode top100(20) 搜索二维矩阵 II

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,2…

腾讯mini项目-【指标监控服务重构】2023-08-24

今日已办 Jeager 功能 监控分布式工作流程并排除故障识别性能瓶颈追踪根本原因分析服务依赖关系 部署 部署 Deployment — Jaeger documentation (jaegertracing.io) 支持 clickhouse jaegertracing/jaeger-clickhouse: Jaeger ClickHouse storage plugin implementation …

Java8实战-总结34

Java8实战-总结34 重构、测试和调试使用 Lambda 重构面向对象的设计模式观察者模式责任链模式 重构、测试和调试 使用 Lambda 重构面向对象的设计模式 观察者模式 观察者模式是一种比较常见的方案&#xff0c;某些事件发生时&#xff08;比如状态转变&#xff09;&#xff0…

Java之转换流的详细解析

2. 转换流 2.1 字符编码和字符集 字符编码 计算机中储存的信息都是用二进制数表示的&#xff0c;而我们在屏幕上看到的数字、英文、标点符号、汉字等字符是二进制数转换之后的结果。按照某种规则&#xff0c;将字符存储到计算机中&#xff0c;称为编码 。反之&#xff0c;将…

docker容器安装MongoDB数据库

一&#xff1a;MongoDB数据库 1.1 简介 MongoDB是一个开源、高性能、无模式的文档型数据库&#xff0c;当初的设计就是用于简化开发和方便扩展&#xff0c;是NoSQL数据库产品中的一种。是最 像关系型数据库&#xff08;MySQL&#xff09;的非关系型数据库。 它支持的数据结构…