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

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

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

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

在这里插入图片描述

文章目录

  • 牛客热题:合并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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【刷题篇】动态规划-完全背包问题(十一)

文章目录 1、完全背包2、零钱兑换3、零钱兑换 II4、完全平方数 1、完全背包 #include <iostream> #include<vector> using namespace std;int main() {int n,v;cin>>n>>v;vector<int> V(n1);vector<int> W(n1);for(int i1;i<n;i){cin&g…

【消息队列】延迟消息

延时消息 延迟消息死信交换机延迟消息的插件 延迟消息 生产者发送消息时指定一个时间&#xff0c;消费者不会立刻收到消息&#xff0c;而在指定时间之后才收到消息 比如说演唱会的票&#xff0c;抢上了但是迟迟未支付&#xff0c;但是库存已经占用&#xff0c;就需要用到延迟消…

【STM32】F405/407的模块总览图,记录查看

从STM32F405/407数据手册中提取&#xff0c;方便以后查看。主要是什么外设连接在什么总线上&#xff0c;时钟频率是多少。 TIM2、3、4、5、12、13、14在APB1上&#xff0c;最大频率84M TIM1、8、9、10、11在APB2上&#xff0c;最大频率168M

WEB攻防-PHP特性-piwigoCMS审计实例

前置知识&#xff1a;PHP函数缺陷 测试环境 &#xff1a;piwigo CMS 漏洞URL&#xff1a; 漏洞文件位置&#xff1a;\include \functions_rate.inc.php 漏洞产生入口文件&#xff1a;/picture.php picture.php中接受了一个GET方法action参数&#xff0c;作为switch...case.…

架设WebSocket的最后一环,如何设置好nginx反向代理

WebScoket都已经完工快一个月&#xff0c;经过一段时间的测试&#xff0c;公司还是准备把服务器换到鹅厂&#xff0c;用EO来解决CDN内容分发和DDOS防护问题&#xff0c;由于EO并不支持URL 路径转发&#xff0c;只支持转发到一个站点的80或则443端口&#xff0c;如果想做路径分发…

Python urllib 爬虫入门(2)

本文为Python urllib类库爬虫更入门的一些操作和爬虫实例及源码。 目录 模拟浏览器请求 简单模拟 设置随机user-agent 请求超时 HTTP请求类型 Get请求 Post请求 抓取网页动态请求 封装ajax请求 调用 循环调用 抓取小说 封装请求函数 把html写入本地分析 调用 正…

Arthas进阶

这里写自定义目录标题 六、class和classloader6、dump7、classloader 七、monitor/watch/trace/stack等核心命令的使用1、monitor2、watch3、trace4、stack5、tt6、option7、profiler 六、class和classloader 6、dump 将已加载类的字节码文件保存到特定目录&#xff1a;logs/…

【IR 论文】HyDE:让 LLM 对 query 做查询改写来改进 Dense Retrieval

论文&#xff1a;Precise Zero-Shot Dense Retrieval without Relevance Labels ⭐⭐⭐⭐ CMU, ACL 2023, arXiv:2212.10496 Code: github.com/texttron/hyde 文章目录 论文速读总结 论文速读 在以往的 dense retrieval 思路中&#xff0c;需要对 input query 做 encode 来得到…

C语言【动态内存】

1.为什么要有动态内存 我们现在掌握的内存开辟方法有&#xff1a; int val 20;//在栈空间开辟4个字节 char str[10]{0};//在栈空间开辟10个字节的连续的空间但是上述的方式有两个点要注意&#xff1a; 1.空间开辟的大小是固定的 2.数组在申明的时候&#xff0c;一定要指定数…

格雷希尔E10系列大电流测试连接器,在新能源汽车大电流接插件的电气测试方案

在新能源汽车的电驱动、电池包等设备的电测试处理中&#xff0c;格雷希尔E10系列电测试连接器具有显著的优势。E10系列的核心设计——插孔/插针&#xff0c;可以达到实验室10万次的插拔寿命&#xff0c;相比传统公母电接头500次左右的连接寿命&#xff0c;E10系列无疑大大减少测…

Golang错误处理机制

文章目录 Golang错误处理机制panic异常recover捕获异常自定义错误 Golang错误处理机制 panic异常 panic异常 Go的类型系统会在编译时捕获很多错误&#xff0c;但有些错误只能在运行时检查&#xff0c;比如除零错误、数组访问越界、空指针引用等&#xff0c;这些运行时错误会引…

实验15 MVC

二、实验项目内容&#xff08;实验题目&#xff09; 编写代码&#xff0c;掌握MVC的用法。 三、源代码以及执行结果截图&#xff1a; inputMenu.jsp&#xff1a; <% page contentType"text/html" %> <% page pageEncoding "utf-8" %> &…

day15 学一下Tailwindcss(java转ts全栈/3r教室)

目前距离全栈差得最多的是前端&#xff0c;而对于前端主要是CSS一直不熟悉&#xff0c;觉得很复杂写起来总是不上道&#xff0c;所以特别关注下Tailwindcss吧&#xff0c;其他前端框架可以先放放&#xff0c;多说无益直接用tailwindcss做个页面试试 看下文档&#xff1a;Tailwi…

【统计推断】-01 抽样原理之(四):中心极限定律

文章目录 一、说明二、样本均值的抽样分布三、两个重要公理四、中心极限定理4.1 定义4.2 中心极限定理的特点4.3 中心极限定理的条件 五、一个举例5.1 一个连续分布示例5.2 样本容量变化的对比 六、结论 关键词&#xff1a;    Central Limit Theorem    Law of Large Numb…

linux部署java1.8(java17)

两种方式&#xff1a; 方式一 1.输入查找命令&#xff1a; yum -y list java*2.输入安装命令&#xff1a; yum install -y java-1.8.0-openjdk.x86_643.测试是否已经安装&#xff1a; java -version方式二&#xff1a; 点击链接进入官网&#xff1a;https://www.oracle.com/…

mysql-sql练习-5-行列互转

目录 成绩单 简单互转 需求 多行转多列 分组 判断 聚合 理解 分组 合并 逆向需求 多列转多行 输出 合并 abc 去重 合并 拆分 需求 建表 多行转多列 逆向需求 多列转多行 拆分 按长度 拆分 按个数 成绩单 简单互转 需求 多行转多列 分组 判断 聚合 with tmp as(--…

3.电源模块趋旺盛,铁路最需可靠性

电源模块趋旺盛&#xff0c;铁路最需可靠性 电源设计需要很高的专业技能。越来越多的电子设备制造商开始采用电源模块来加快设计周期。通信、铁路、电力和军工领域&#xff0c;对电源模块需求越来越旺盛。 通信网络基建设备市场潜力巨大。应市场要求&#xff0c;现代的通信系…

自动化工具:推广神器,精准获客新策略

在当今这个信息爆炸的时代&#xff0c;推广和获客对于企业的生存和发展至关重要。然而&#xff0c;传统的推广方式不仅耗时耗力&#xff0c;而且效果往往难以精准把控。此时&#xff0c;自动化工具的出现无疑为市场推广带来了新的生机。本文将以客观公正的态度探讨如何利用自动…

[软件工具]批量根据文件名查找PDF文件复制到指定的地方,如何批量查找文件复制,多个文件一起查找复制

多个文件目录下有多个PDF, 如何根据文件名一个清单&#xff0c;一次性查找多个PDF复制保存 如图所示下面有7个文件夹&#xff0c;每个文件夹里面有几百上千PDF文件 如何从上千个PDF文件中一次性快速找到我们要的文件呢 &#xff1f; 我们需要找到文件名是这样的PDF&#xff0…

oracle pl/sql 如何让sql windows 显示行号

oracle pl/sql 如何让sql windows 显示行号 下载最新版的pl/sql第一步&#xff0c;在preferences中对sql Windows进行设置&#xff0c;如下所示第二步&#xff0c;在preferences中对User interface进行设置&#xff0c;如下所示结果如下 其实很简单 下载最新版的pl/sql 官方下…