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;
     }
 }
};

总结

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

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

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

相关文章

imgaug库指南(四):从入门到精通的【图像增强】之旅

引言 在深度学习和计算机视觉的世界里&#xff0c;数据是模型训练的基石&#xff0c;其质量与数量直接影响着模型的性能。然而&#xff0c;获取大量高质量的标注数据往往需要耗费大量的时间和资源。正因如此&#xff0c;数据增强技术应运而生&#xff0c;成为了解决这一问题的…

AntDB内存管理之内存上下文

1. 主题说明 AntDB的内存管理在开发时&#xff0c;使用了内存上下文机制来实现内存管理。本文就从AntDB的内存上下文机制出发&#xff0c;解析内存上下文的实现原理。AntDB的代码中&#xff0c;涉及到内存的处理时&#xff0c;经常会看到下面这样的代码。 图1&#xff1a;切换…

SpringBean的生命周期

SpringBean Bean的生命周期 1、首先需要明确bean对象与普通对象的区别: 对于普通的 Java 对象&#xff0c;当 new 的时候创建对象&#xff0c;然后该对象就能够使用了。一旦该对象不再被使用&#xff0c;则由 Java 自动进行垃圾回收。 而 Spring 中的对象是 bean&#xff0c;…

Gin 路由注册与请求参数获取

Gin 路由注册与请求参数获取 文章目录 Gin 路由注册与请求参数获取一、Web应用开发的两种模式1.前后端不分离模式2.前后端分离模式 二、RESTful介绍三、API接口3.1 RESTful API设计指南3.2 API与用户的通信协议3.3 RestFul API接口设计规范3.3.1 api接口3.3.2 接口文档&#xf…

C++_模板

目录 1、函数模板 1.2 模板原理 2、多个模板参数 3、模板的显示实例化 4、模板的匹配 5、类模板 结语&#xff1a; 前言&#xff1a; 在C中&#xff0c;模板分为函数模板和类模板&#xff0c;而模板的作用就是避免了重复的工作&#xff0c;把原本是程序员要做的重复工作…

内网DNS隐蔽隧道搭建之iodine工具

iodine iodine是基于C语言开发的&#xff0c;分为服务端和客户端。iodine支持转发模式和中继模式。其原理是&#xff1a;通过TAP虚拟网卡&#xff0c;在服务端建立一个局域网&#xff1b;在客户端&#xff0c;通过TAP建立一个虚拟网卡&#xff1b;两者通过DNS隧道连接&#xf…

YACS(上海计算机学会竞赛平台)2023年12月月赛——移动复位

移动复位 内存限制: 256 Mb时间限制: 1000 ms 题目描述 二维平面上有一个点。该点最初所在的位置称之为起点。接下来&#xff0c;该点接受了一串命令&#xff0c;每个命令可以用一个大写字母表示&#xff1a; R 表示该点沿 X 轴坐标正方向移动了一个单位&#xff1b;L 表示…

AI实景无人直播创业项目:开启自动直播新时代,一部手机即可实现增长

在当今社会&#xff0c;直播已经成为了人们日常生活中不可或缺的一部分。无论是商家推广产品、明星互动粉丝还是普通人分享生活&#xff0c;直播已经渗透到了各行各业。然而&#xff0c;传统直播方式存在着一些不足之处&#xff0c;如需现场主持人操作、高昂的费用等。近年来&a…

CentOs 环境下使用 Docker 部署 Ruoyi-Vue

CentOs 环境下使用 Docker 部署 Ruoyi-Vue RuoYi-Vue 项目下载地址 RuoYi-Vue: &#x1f389; 基于SpringBoot&#xff0c;Spring Security&#xff0c;JWT&#xff0c;Vue & Element 的前后端分离权限管理系统&#xff0c;同时提供了 Vue3 的版本 (gitee.com) Docker 部…

x-cmd pkg | tig - git 文本模式界面

目录 简介首次用户功能特点类似工具与竞品进一步探索 简介 tig 由 Jonas Fonseca 于 2006 年使用 C 语言创建的 git 交互式文本命令行工具。旨在开启交互模式快速浏览 git 存储库的信息以及 git 命令的运行。 首次用户 使用 x tig 即可自动下载并使用 在终端运行 eval "…

NeurIPS上新 | 从扩散模型、脑电表征,到AI for Science,微软亚洲研究院精选论文

编者按&#xff1a;欢迎阅读“科研上新”栏目&#xff01;“科研上新”汇聚了微软亚洲研究院最新的创新成果与科研动态。在这里&#xff0c;你可以快速浏览研究院的亮点资讯&#xff0c;保持对前沿领域的敏锐嗅觉&#xff0c;同时也能找到先进实用的开源工具。 本期“科研上新…

项目框架构建之6:编写通用主机基础类

本文是“项目框架构建”系列之6&#xff0c;本文介绍如何编写通用主机基础类。 1.为了构建通用主机&#xff0c;我们先创建主机接口IAppHost接口 接口需要有配置项&#xff0c;我们定义为HostConfiguration&#xff0c;比如我们希望用户可以设定他的工作目录&#xff0c;就可…

GLEE:一个模型搞定目标检测/实例分割/定位/跟踪/交互式分割等任务!性能SOTA!

GLEE&#xff0c;这是一个面向目标级别的基础模型&#xff0c;用于定位和识别图像和视频中的目标。通过一个统一的框架&#xff0c;GLEE实现了对开放世界场景中任意目标的检测、分割、跟踪、定位和识别&#xff0c;适用于各种目标感知任务。采用了一种协同学习策略&#xff0c;…

C之BS开发

一、 BS 概述与 boa 搭建 1.1 BS 模式开发概述 BS 模式&#xff1a; 浏览器与服务器模式&#xff0c; 即通过浏览器访问服务器的 Web 资源。 1.1.1 web 前端开发技术 主要包含&#xff1a; HTML 、 CSS 、 XML/JSON 、 Javascript 、 AJAX HTML 超文本标记语言 ( 英文全称…

华为欧拉安装部署:Oracle11g

一、环境准备 1、下载安装低版本的libaio包&#xff1b;libaio版本太高&#xff0c;会造成编译错误 查看libaio1库版本不能大于0.3.109 [oracles3 install]$ rpm -qa libaio libaio-0.3.110-12.el8.x86_64# 查看欧拉操作系统版本 [oraclelocalhost bin]$ cat /etc/os-release…

stable diffusion 基础教程-提示词之艺术风格用法

展现夕阳 golden hour, (rim lighting):1.2, warm tones, sun flare, soft shadows, vibrant colors, hazy glow, painterly effect, dreamy atmosphere阴影 chiaroscuro, (high contrast):1.2, dramatic shadows, bold highlights, moody atmosphere, captivating inte…

5-sql注入之文件读写

文章目录 SQL注入之文件读写1、文件读写注入的原理2、文件读写注入的条件读取文件写入文件 SQL注入之文件读写 1、文件读写注入的原理 就是利用文件的读写权限进行注入&#xff0c;它可以写入一句话木马&#xff0c;也可以读取系统文件的敏感信息。 2、文件读写注入的条件 …

02 Deep learning algorithm

Neural Networks target&#xff1a; inference&#xff08;prediction&#xff09;training my own modelpractical advice for building machine learning systemdecision Tress application: speech&#xff08;语音识别&#xff09; ----> images(计算机视觉)—> t…

MS713/MS713T:CMOS 低压、4Ω四路单刀单掷开关,替代ADG713

产品简述 MS713/MS713T 是一款单芯片 CMOS 4 路可选择开关&#xff0c;具有低 功耗、高开关速度、低导通阻抗、低漏电和高带宽特性。其工作 电压范围是 1.8V 到 5.5V &#xff0c;可以广泛应用在电池供电仪器仪表、新 一代的模数转换和数模转换系统中。其高带宽特性可用在 …

代码+视频,手把手教你R语言使用forestploter包绘制单组及双组森林图

森林图在论文中很常见&#xff0c;多用于表示多因素分析中的变量与结果变量的比值效应&#xff0c;可以用图示的方法比较直观的绘制出来。既往我们在文章《R语言快速绘制多因素回归分析森林图&#xff08;1&#xff09;》已经介绍了怎么绘制森林图&#xff0c;但是绘图比较简单…