牛客热题:合并K个升序链表

news2025/5/14 7:56:59

📟作者主页:慢热的陕西人

🌴专栏链接:力扣刷题日记

📣欢迎各位大佬👍点赞🔥关注🚓收藏,🍉留言

在这里插入图片描述

文章目录

  • 牛客热题:合并K个升序链表
    • 题目链接:
    • 方法一:复用2个升序链表的方法
      • 思路:
      • 代码:
      • 复杂度:
    • 方法二:第一种方法的分治优化-->借鉴牛客题解
      • 思路:
      • 代码:
      • 复杂度:
    • 方法三:优先队列-->借鉴牛客题解
      • 思路:
      • 代码:
      • 复杂度:

牛客热题:合并K个升序链表

题目链接:

合并k个已排序的链表_牛客题霸_牛客网 (nowcoder.com)

方法一:复用2个升序链表的方法

思路:

  • 首先我们知道如何合并两个升序链表
  • 那么我们先将k个的前两个合并,然后再将和这个合并的链表和下一个链表合并…直到所有的链表都被合并

代码:

 ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        //申请一个哨兵位
        ListNode* head = new ListNode(0);
 
        ListNode* cur = head;
        while(pHead1 != nullptr && pHead2 != nullptr)
        {
            if(pHead1->val <= pHead2->val)
            {
                cur->next = pHead1;
                cur = cur->next;
                pHead1 = pHead1->next;
            }
            else
            {
                cur->next = pHead2;
                cur = cur->next;
                pHead2 = pHead2->next;
            }
        }
 
        //p1未完的情况
        while(pHead1 != nullptr)
        {
            cur->next = pHead1;
            cur = cur->next;
            pHead1 = pHead1->next;
        }
 
        //p2未完的情况
        while(pHead2 != nullptr)
        {
            cur->next = pHead2;
            cur = cur->next;
            pHead2 = pHead2->next;
        }
 
        return head->next;
    }
    
    ListNode* mergeKLists(vector<ListNode*>& lists) 
    {
        if(lists.size() == 0) return nullptr;
        ListNode* ret = lists[0];

        for(int i = 1; i < lists.size(); ++i)
        {
            ret = Merge(ret, lists[i]);
        }  

        return ret;
    }

复杂度:

时间复杂度:O( N 2 N^2 N2), 但其实一般达不到O( N 2 N^2 N2);

  • 对于第一个链表:我们遍历了k-1次
  • 对于第二个链表:我们遍历了k-2次
  • 对于最后一个链表:我们遍历了1次

由于所有的链表的长度加起来为 n n n,那么平均长度为 n / k n / k n/k,

每个链表最多被遍历k - 1次,我们放缩为k次,那么需要最多 n ∗ n n*n nn次运算.

空间复杂度:O(1), 使用了常数个额外的空间。

方法二:第一种方法的分治优化–>借鉴牛客题解

思路:

具体做法:

  • step 1:从链表数组的首和尾开始,每次划分从中间开始划分,划分成两半,得到左边 n / 2 n/2 n/2个链表和右边 n / 2 n/2 n/2个链表。
  • step 2:继续不断递归划分,直到每部分链表数为1.
  • step 3:将划分好的相邻两部分链表,按照两个有序链表合并的方式合并,合并好的两部分继续往上合并,直到最终合并成一个链表。

合并k个升序链表

代码:

     ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
    {
        //申请一个哨兵位
        ListNode* head = new ListNode(0);
 
        ListNode* cur = head;
        while(pHead1 != nullptr && pHead2 != nullptr)
        {
            if(pHead1->val <= pHead2->val)
            {
                cur->next = pHead1;
                cur = cur->next;
                pHead1 = pHead1->next;
            }
            else
            {
                cur->next = pHead2;
                cur = cur->next;
                pHead2 = pHead2->next;
            }
        }
 
        //p1未完的情况
        while(pHead1 != nullptr)
        {
            cur->next = pHead1;
            cur = cur->next;
            pHead1 = pHead1->next;
        }
 
        //p2未完的情况
        while(pHead2 != nullptr)
        {
            cur->next = pHead2;
            cur = cur->next;
            pHead2 = pHead2->next;
        }
 
        return head->next;
    }
    
    ListNode* DivideMerge(vector<ListNode*> & lists, int l, int r)
    {
        //不存在区间
        if(l > r) return nullptr;
        //已到达最小的区间
        if(l == r) return lists[l];

        int mid = l + r >> 1;

        return Merge(DivideMerge(lists, l, mid), DivideMerge(lists, mid + 1, r));
    }

    ListNode* mergeKLists(vector<ListNode*>& lists) 
    {
        return DivideMerge(lists, 0, lists.size() - 1);
    }

复杂度:

  • 时间复杂度: O ( n l o g 2 K ) O(nlog_2K) O(nlog2K),其中 n n n为所有链表的总节点数,分治为二叉树型递归,最坏情况下二叉树每层合并都是O(N)个节点,因为分治一共有 O ( l o g 2 K ) O(log_2K) O(log2K)
  • 空间复杂度: O ( l o g 2 K ) O(log_2K) O(log2K),最坏的情况需要向下递归 l o g 2 K log_2K log2K层,需要 l o g 2 K log_2K log2K个函数栈帧

方法三:优先队列–>借鉴牛客题解

思路:

如果非要按照归并排序的合并思路,双指针不够用,我们可以直接准备k个指针,每次比较得出k个数字中的最小值,我们可以借助堆,也就是优先队列—>priority_queue来完成这一点。

代码:

   struct cmp
    {
        bool operator()(ListNode* a, ListNode* b)
        {
            return a->val > b->val;
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) 
    {
        //小根堆
        priority_queue<ListNode*, vector<ListNode*>, cmp> pq;

        //遍历所有链表的第一个元素,并且把不为空的加入到优先队列
        for(int i = 0; i < lists.size(); ++i)
        {
            if(lists[i] != nullptr) pq.push(lists[i]);
        }

        ListNode* res = new ListNode(-1);
        ListNode* cur = res;
        while(!pq.empty())
        {
            //取出最小的元素
            ListNode* t = pq.top();
            pq.pop();
            //链接到尾部
            cur->next = t;
            cur = cur->next;
            
            //将该链表的下一个指针加入到优先队列
            if(t->next != nullptr)
            pq.push(t->next);
        }

        return res->next;
    }

复杂度:

  • 时间复杂度: O ( n l o g 2 K ) O(nlog_2K) O(nlog2K),其中 n n n为所有链表的总节点数,每次加入优先队列的复杂度为 O ( l o g 2 K ) O(log_2K) O(log2K)
  • 空间复杂度: O ( K ) O(K) O(K),优先队列的大小为K

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

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

相关文章

周三多《管理学原理》第3版/考研真题/章节练习题

普通高等教育“十一五”国家级规划教材《管理学原理》&#xff08;第3版&#xff0c;周三多、陈传明、龙静编著&#xff0c;南京大学出版社&#xff09;是我国高校广泛采用的管理学权威教材之一&#xff0c;也被众多高校&#xff08;包括科研机构&#xff09;指定为考研考博专业…

开源医疗大模型排行榜: 健康领域大模型基准测试

开源医疗大模型排行榜: 健康领域大模型基准测试 文章目录 开源医疗大模型排行榜: 健康领域大模型基准测试一、引言二、数据集、任务和评估设置1、MedQA2、MedMCQA3、PubMedQA4、MMLU 子集 (医学和生物学) 三、洞察与分析四、提交你的模型以供评估五、下一步是什么&#xff1f;扩…

node.js 解析post请求 方法二

前提&#xff1a;以前面发的node.js解析post请求方法一为模板&#xff0c;具体见 http://t.csdnimg.cn/ABaIn 此文我们运用第二种方法&#xff1a;使用第三方模块formidable对post请求进行解析。 1》代码难点 *** 在Node.js中使用formidable模块来解析POST请求主要涉及到处理…

74、堆-数组中的第K个最大元素

思路&#xff1a; 直接排序是可以的&#xff0c;但是时间复杂度不符合。可以使用优先队列&#xff0c;代码如下&#xff1a; class Solution {public int findKthLargest(int[] nums, int k) {if (numsnull||nums.length0||k<0||k>nums.length){return Integer.MAX_VAL…

网工内推 | 互联网大厂百度、虎牙项目管理岗,15薪,PMP认证优先

01 百度在线 招聘岗位&#xff1a;商业项目管理组_项目管理 职责描述&#xff1a; 1. 商业部核心项目管理工作&#xff0c;主导制定项目目标、计划&#xff0c;推进项目实施及交付&#xff0c;有效管控项目进度、成本、质量、风险等 2. 商业技术/业务创新氛围建设&#xff0c;…

SQL底层执行过程

MySQL 的查询流程 客户端请求连接器 负责与客户端的通信,是半双工模式&#xff08;半双工(Half Duplex)数据传输指数据可以在一个信号载体的两个方向上传输,但是不能同时传输。&#xff09;&#xff0c;验证请求用户的账户和密码是否正确&#xff0c;③如果用户的账户和密码验…

Linux基础——Linux开发工具(下)_make/makefile

前言&#xff1a;在经过前面两篇学习&#xff0c;大家对Linux开发工具都有一定的了解&#xff0c;而在此之前最重要的两个工具就是vim&#xff0c;gcc。 如果对这两个工具不太了解&#xff0c;可以先阅读这两篇文章&#xff1a; Linux开发工具 (vim) Linux开发工具 (gcc/g) 首先…

跟TED演讲学英文:Innovating to zero! by Bill Gates

Innovating to zero! Link: https://www.ted.com/talks/bill_gates_innovating_to_zero Speaker: Bill Gates Date: February 2010 文章目录 Innovating to zero!IntroductionVocabularyTranscriptQ&A with Chris AndersonSummary后记 Introduction At TED2010, Bill Ga…

.NET C# ORM 瀚高数据库

SqlSugar ORM SqlSugar 是一款 老牌 .NET开源ORM框架&#xff0c;由果糖大数据科技团队维护和更新 &#xff0c;开箱即用最易上手的ORM 优点 &#xff1a;【生态丰富】【高性能】【超简单】 【功能全面】 【多库兼容】【适合产品】 【SqlSugar视频教程】 支持 &#xff1a…

判断字符串由几个单词组成(C语言)

一、N-S流程图&#xff1b; 二、运行结果&#xff1b; 三、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int world 0;int i 0;char c 0;char string[81] { 0 };int num 0;//提示用户&#xff…

一个docker配置mysql主从服务器

这也就是因为穷&#xff0c;不然谁用一个docker配置主从&#xff0c;哈哈 既然成功了就记录下。过程挺折磨人的。 首先要保证你的电脑安装好了docker 为了保证docker当中主从能正常连网&#xff0c;现在docker里面创建一个网络环境 docker network create --driver bridge mysq…

C++-9

C 1.已知C风格的字符串&#xff0c;完成对字符串通过下标访问时的异常处理机制(越界访问) 2.写一个程序&#xff0c;程序包含两个类&#xff0c;类中实现一个成员函数&#xff0c;MyGetChar(), 类A中每调用一 次&#xff0c;按顺序得到一个数字字符&#xff0c;比如第-次调用得…

社交论坛问答发帖系统源码-java+vue+uniapp开发前后端

源码说明&#xff1a; 前后端分离社交论坛问答发帖BBS源码&#xff0c;社交论坛小程序|H5论坛。 下 载 地 址 &#xff1a; runruncode.com/php/19462.html 该项目是一个使用Java、Vue和Uniapp开发的前后端分离的社交论坛问答发帖/BBS项目。它包括了论坛图文帖、视频、圈子…

新唐的nuc980/nuc972的开发1-环境和源码同步

开发环境安装 1.1更新源 服务器端&#xff1a;可以参考&#xff1a;Linux替换清华源_更改清华源-CSDN博客 下面是桌面端的方法&#xff1a; 打开系统的软件中心&#xff0c;选择自己想要使用的源 更新缓存 1.2安装必须的库 apt-get install patch apt-get install libc6-dev …

SQL提升

1. SQL TOP 子句 TOP 子句用于规定要返回的记录的数目。 对于拥有数千条记录的大型表来说&#xff0c;TOP 子句是非常有用的。 **注释&#xff1a;**并非所有的数据库系统都支持 TOP 子句。 1.1 SQL TOP 语法 SQL Server 的语法&#xff1a; SELECT TOP number|percent c…

C#基础|了解对象在程序中的状态及垃圾回收机制

哈喽&#xff0c;你好啊&#xff0c;我是雷工&#xff01; 本节了解对象的生命周期及对象状态和垃圾回收机制&#xff0c;以下为学习笔记。 1、对象的生命周期 对象在内存中不断地被引用&#xff0c;被释放&#xff0c;形成了类似生命周期的过程。 2、对象在内存中的状态 对…

记一次生产事故的排查和解决

一. 事故概述 春节期间, 生产系统多次出现假死不可用现象, 导致绝大部分业务无法进行. 主要表现现象为接口无法访问. 背景为900W客户表和近实时ES, 以及春节期间疫情导致的普通卖菜场景近似秒杀等. 二. 排查过程 优先排查了info, error, catalina日志, 发现以下异常: 主要的…

一文掌握Vue依赖注入:原理、应用场景以及最佳模块化与单元测试实践,提升代码的可维护性与模块化程度

Vue 中的依赖注入&#xff08;Dependency Injection, DI&#xff09;机制通过 provide 与 inject API&#xff0c;实现了跨组件层级间的数据与服务透明传递&#xff0c;使父组件能够向其任意深度的子孙组件“注入”依赖&#xff0c;而不需要通过层层传递 props 或使用全局状态管…

搭建智能客服机器人设计流程

一、检索型机器人FAQ-Bot 在客服处理的问题中70%都是简单的问答业务&#xff0c;只要找到QA知识库中与用户当前问句语义最相近的标准问句&#xff0c;取出答案给用户就可以了。FAQ-Bot就是处理这类问题的。在没有使用深度学习算法之前&#xff0c;通常采用检索NLP技术处理。 …

如何用智能获客开启新商机?揭秘赢销侠软件的奇效

在当今数字化竞争日益激烈的商业环境中&#xff0c;企业为了生存和发展&#xff0c;必须寻找新的途径以获取潜在客户。智能获客作为一种新型的营销方式&#xff0c;正以其高效、精准的特点改变着传统的市场开拓模式。而在这个过程中&#xff0c;自动获客软件的作用愈发凸显&…