C/C++ BM4 合并两个排序的链表

文章目录

  • 前言
  • 题目
  • 1. 解决方案一
    • 1.1 思路概述
    • 1.2 源码
  • 2. 解决方案二
    • 2.1 思路阐述
    • 2.2 源码
  • 总结

前言

这道题采用两种方式,一种是直接插入法,还有一种就是递归调用。


题目

输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。
数据范围: 0≤n≤1000,−1000≤节点值≤1000
要求:空间复杂度 O(1),时间复杂度 O(n

如输入{1,3,5},{2,4,6}时,合并后的链表为{1,2,3,4,5,6},所以对应的输出为{1,2,3,4,5,6},转换过程如下图所示:
在这里插入图片描述
或输入{-1,2,4},{1,3,4}时,合并后的链表为{-1,1,2,3,4,4},所以对应的输出为{-1,1,2,3,4,4},转换过程如下图所示:
在这里插入图片描述

在这里插入图片描述


1. 解决方案一

1.1 思路概述

合并链表的过程就是插入节点的过程,不过是双链表遍历。
首先判断两个链表的最小节点谁的最小,那么链表首节点小的作为基链表,另一个链表进行比较与插入。
一般链表题都要添加一个头结点,作为哨兵节点,这样的好处是确保每一个节点都有一个前置节点。

对于题目中的特殊情况,空链表这种,我们得单独拎出来判断。如果一个链表是空链表,则直接返回另一个非空链表;如果两个链表都为空,则直接返回空链表。

正常判断的情况,这里以pHead1为基链表的情况(也就是pHead1的第一个节点小于pHead2的第一个节点)为例。
我们通过一个bool类型变量来确定基链表判断逻辑。

如果pHead2链表的值小于pHead1指向的节点的下一个值,就进行插入。比如,1,3,5的基链表,2,4,6链表往里面插入,因为我们已经通过首节点判断出pHead2的首节点肯定比pHead1的节点大,我们只需要找到pHead1中第一个比pHead2中要插入到pHead1的节点大的节点即可。所以这里用到了pHead->next->val。

后面就是断链和插入的操作,再接着就是双链表遍历,即调整双链表中指针的位置。

如果pHead1>pHead2的情况,那么逻辑是基本一致的,这里就不在赘述。

1.2 源码

/*** struct ListNode {*  int val;*  struct ListNode *next;*  ListNode(int x) : val(x), next(nullptr) {}* };*/
class Solution {public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param pHead1 ListNode类* @param pHead2 ListNode类* @return ListNode类*/ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {ListNode* rec = new ListNode(-1);if (!pHead1 && !pHead2) {return nullptr;}if (!pHead1 && pHead2) {return pHead2;}if (pHead1 && !pHead2) {return pHead1;}//比较链表大小bool firstListBig = true;if (pHead1->val > pHead2->val) {firstListBig = true;rec->next = pHead2;} else {firstListBig = false;rec->next = pHead1;}//第二个链表大的情况if (!firstListBig) {while (pHead2 && pHead1) {//如果小链表后面没有节点了,则大链表直接加到小链表后if (!pHead1->next) {pHead1->next = pHead2;break;}ListNode* tempNode = pHead2->next;if (pHead2->val <= pHead1->next->val) {pHead2->next = pHead1->next;pHead1->next = pHead2;pHead2 = tempNode;pHead1 = pHead1->next;} else {pHead1 = pHead1->next;if (!pHead1->next) {pHead1->next = pHead2;break;}}}} else //第二个链表小的情况{while (pHead2 && pHead1) {if (!pHead2->next) {pHead2->next = pHead1;break;}ListNode* tempNode = pHead1->next;if (pHead1->val <= pHead2->next->val) {pHead1->next = pHead2->next;pHead2->next = pHead1;pHead1 = tempNode;pHead2 = pHead2->next;} else {pHead2 = pHead2->next;if (!pHead2->next) {pHead2->next = pHead1;break;}}}}return rec->next;}
};

2. 解决方案二

2.1 思路阐述

使用递归的方式进行处理。

写递归代码,最重要的要明白递归函数的功能。可以不必关心递归函数的具体实现。
比如这个ListNode* Merge(ListNode* pHead1, ListNode* pHead2)
函数功能:合并两个单链表,返回两个单链表头结点值小的那个节点。

如果知道了这个函数功能,那么接下来需要考虑2个问题:

递归函数结束的条件是什么?(这个非常重要,一般第一个就要写它)
递归函数一定是缩小递归区间的,那么下一步的递归区间是什么?

对于问题1.对于链表就是,如果为空,返回什么
对于问题2,跟迭代方法中的一样,如果PHead1的所指节点值小于等于pHead2所指的结点值,那么phead1后续节点和pHead节点继续递归。这个就类似于去找到一个pHead1中所指节点第一个比pHead2所指节点大的节点。

时间复杂度:O(m+n)
空间复杂度:O(m+n),每一次递归,递归栈都会保存一个变量,最差情况会保存(m+n)个变量

递归的一个大致流程,我画了一下,其实大家可以自己debug一下就知道了
在这里插入图片描述

2.2 源码

class Solution {
public:ListNode* Merge(ListNode* pHead1, ListNode* pHead2){if (!pHead1) return pHead2;if (!pHead2) return pHead1;if (pHead1->val <= pHead2->val) {pHead1->next = Merge(pHead1->next, pHead2);return pHead1;}else {pHead2->next = Merge(pHead1, pHead2->next);return pHead2;}}
};

总结

这道题的第一个迭代方法是我最先想到的,代码也比较好写。第二个方法是看题解,这里整合下来作为参考。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Java图书借阅管理系统设计与实现(源码+部署文档)

博主介绍&#xff1a; ✌至今服务客户已经1000、专注于Java技术领域、项目定制、技术答疑、开发工具、毕业项目实战 ✌ &#x1f345; 文末获取源码联系 &#x1f345; &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅 &#x1f447;&#x1f3fb; 不然下次找不到 Java项目精品实…

python可视化界面自动生成,python如何做可视化界面

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python gui可视化操作界面制作&#xff0c;python做出的炫酷的可视化&#xff0c;现在让我们一起来看看吧&#xff01; 目录 前言 一.环境配置 插件&#xff1a; 1.python 2.Chinese 3.Open In Default Browser 安装pyt…

JavaScript系列——正则表达式

文章目录 需求场景正则表达式的定义创建正则表达式通过 / 表示式/ 创建通过构造函数创建 编写一个正则表达式的模式使用简单模式使用特殊字符常用特殊字符列表特殊字符组和范围 正则表达式使用代码演示 常用示例验证手机号码合法性 小结 需求场景 在前端开发领域&#xff0c;在…

AJAX:整理3:原生AJAX的相关操作

注意AJAX的步骤 // 1.创建对象 const xhr new XMLHttpRequest()// 2.初始化 设置 请求方法 和 url xhr.open("GET", "http://localhost:9090/server")// 3.发送 xhr.send()// 4.事件绑定 处理服务端返回的结果 // readyState 是xhr对象中的属性&#xff…

链表的一些典型问题

求链表的中间节点/倒数第K个节点 等类似的随机访问&#xff0c;可以考虑用快慢指针 例 求链表的中间节点 可以定义两个指针&#xff0c;一个一次走两步一个一次走一步&#xff0c;当走的快的走到NULL时&#xff0c;走的慢的就是链表的中间节点。&#xff08;此法求出的偶数个…

2023年03月18日_微软office365 copilot相关介绍

文章目录 Copilot In WordCopilot In PowerpointCopilot In ExcelCopilot In OutlookCopilot In TeamsBusiness Chat1 - copilot in word2 - copilot in excel3 - copilot in powerpoint4 - copilot in outlook5 - copilot in teams6 - business chat word 1、起草草稿 2、自动…

1.Linux快速入门

Linux快速入门 Linux操作系统简介Linux操作系统优点Linux操作系统发行版1. Red Hat Linux2. CentOS3. Ubuntu4. SUSE Linux5. Fedora Linux 32位与64位操作系统的区别Linux内核命名规则 Linux操作系统简介 Linux操作系统是基于UNIX以网络为核心的设计思想&#xff0c;是一个性…

vue3 组件之间传值

vue3 组件之间传值 非常好&#xff0c;为啥突然开这样一篇博文&#xff0c;首先是因为 vue3 是未来发展的趋势。其次&#xff0c;vue 官方已经确认&#xff0c;将于2023年最后一天停止对 vue2 项目的维护&#xff0c;这个是官方发出的通知&#xff0c;并且呢&#xff0c;尤雨溪…

实现二叉树的基本操作与OJ练习

目录 1.二叉树的基本操作 1.1二叉树基本操作完整代码 1.2检测value值是否存在 1.3层序遍历 1.4判断一棵树是不是完全二叉树 2.OJ练习 2.1平衡二叉树 2.2对称二叉树 2.3二叉树遍历 1.二叉树的基本操作 1.1二叉树基本操作完整代码 public class BinaryTree {static…

UDP信号多个电脑的信息传输测试、配置指南

最近要做一个东西&#xff0c;关于一个软件上得到的信号&#xff0c;如何通过连接的局域网&#xff0c;将数据传输出去。我没做过相关的东西&#xff0c;但是我想应该和软件连接数据库的过程大致是差不多的&#xff0c;就一个ip和一个端口号啥的。 一.问题思路 多个设备同时连…

Linux系统下隧道代理HTTP

在Linux系统下配置隧道代理HTTP是一个涉及网络技术的话题&#xff0c;主要目的是在客户端和服务器之间建立一个安全的通信通道。下面将详细解释如何进行配置。 一、了解基本概念 在开始之前&#xff0c;需要了解几个关键概念&#xff1a;代理服务器、隧道代理和HTTP协议。代理…

【docker实战】01 Linux上docker的安装

Docker CE是免费的Docker产品的新名称&#xff0c;Docker CE包含了完整的Docker平台&#xff0c;非常适合开发人员和运维团队构建容器APP。 Ubuntu 14.04/16.04&#xff08;使用 apt-get 进行安装&#xff09; # step 1: 安装必要的一些系统工具 sudo apt-get update sudo ap…