每日一题---OJ题: 合并两个有序链表

嗨!小伙伴们,好久不见啦! 今天我们来看看一道很有意思的一道题---合并两个有序链表

嗯,题目看上去好像不难,我们一起画图分析分析吧!

上图中,list1有3个结点,分别为1,2,3 ; list2中有3个结点,分别为1,3,4, 题目要求我们要将这两个链表合并到一起,并且是升序,最后将链表返回。

思路1:定义2个变量,l1和l2,分别指向list1和list2,它们从头遍历链表,依次比较每个结点的数据域,如果l1指向的结点的数据域小于l2指向的结点的数据域,那么就将l1尾插到新链表中; 反之亦然。

当 l1 && l2 不为空的时候,进入while循环(注意是 &&,因为只要有一个不满足条件,就可以跳出while循环),判断第一个结点,判断完毕后,尾插到新链表中(如果新链表为空,那么这个结点就是链表的头结点和尾结点 ; 如果链表不为空,这个结点就是链表的新的尾结点)。

第一次:  将list2中第一个结点尾插到新链表中,该结点就是链表的头结点和尾结点。l2继续往后遍历链表。

第二次:l1指向的结点的数据域小于l2,因此将该结点尾插到新链表中,这个结点就是链表的新的尾结点,l1指向下一个结点。

第三次:l1指向的结点的数据域小于l2,因此将该结点尾插到新链表中,这个结点就是链表的新的尾结点,l1指向下一个结点。

第四次: l2指向的结点的数据域小于l1,因此将该结点尾插到新链表中,这个结点就是链表的新的尾结点,l2指向下一个结点。

第五次:

第六次:

好啦,大致思路就是这样,接下来我们开始实现吧!

首先,定义2个变量l1和l2,分别指向list1和list2; 其次,我们定义新链表的表头newHead和表尾newTail。

struct ListNode* l1 = list1;                    //定义l1变量,指向list1
struct ListNode* l2 = list2;                    //定义l2变量,指向list2struct ListNode* newHead = NULL;                //定义新链表的头结点
struct ListNode* newTail = NULL;                //定义新链表的尾结点

当  l1 && l2不为空,进入循环,依次比较每一个结点。

 while( l1 && l2){if(l1->val < l2->val){//l1比l2小if(newTail == NULL){//如果链表为空newHead = newTail = l1;}else{//链表不为空newTail->next = l1;newTail = l1;}l1 = l1->next;        //l1指向下一个结点}else{//l2比l1小if(newTail == NULL){//如果链表为空newHead = newTail = l2;}else{//链表不为空newTail->next = l2;newTail = l2;}l2 = l2->next;        //l2指向下一个结点}
}

是不是这里就结束了呢? 当然不是! 当 l1 走到NULL的位置 或者 l2 走到空的位置, 会跳出循环,来到后面的代码。

当 l1还未遍历完链表时,我们只需要将 newTail的next指针指向 l1 就可以啦! 用 if条件来做判断,本身就只让它执行一次,因为链表最后剩下的,就直接往后挂了,链表的每一个结点是通过next指针链接的,找到一个结点,就可以找到后续的所有结点。

(就像老鹰捉小鸡一样,是不是从中间折断的话,那后面的那些人还是连在一起的,重新连接的话,那只用把后半段的第一个人找到,挂回去,那后面的人也就一并连接回去了。)

if(l1){//l1没有遍历完链表newTail->next = l1;}if(l2){//l2没有遍历完链表newTail->next = l2;}

好啦,最后我们返回newHead就可以啦! 但是还有一个小小的问题需要注意: 传过来的参数 list1 或者 list2 有可能为空, 因此我们需要在开始就判断一下它们是否为空。

 if(list1 == NULL){//如果list1为空,则返回list2return list2;}if(list2 == NULL){//如果list2为空,则返回list1return list1;}

OK,整体代码如下: 

 typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if(list1 == NULL){//如果list1为空,则返回list2return list2;}if(list2 == NULL){//如果list2为空,则返回list1return list1;}ListNode* l1 = list1;//定义l1变量,指向list1ListNode* l2 = list2; //定义l2变量,指向list2ListNode* newHead = NULL; //定义新链表的头结点ListNode* newTail = NULL; //定义新链表的尾结点while( l1 && l2){if(l1->val < l2->val){//l1比l2小if(newTail == NULL){//如果链表为空newHead = newTail = l1;}else{//链表不为空newTail->next = l1;newTail = l1;}l1 = l1->next;        //l1指向下一个结点}else{//l2比l1小if(newTail == NULL){//如果链表为空newHead = newTail = l2;}else{//链表不为空newTail->next = l2;newTail = l2;}l2 = l2->next;      //l2指向下一个结点}
}if(l1){//l1没有遍历完链表newTail->next = l1;}if(l2){//l2没有遍历完链表newTail->next = l2;}return newHead; //返回头结点
}

好的,这道题我们基本上做完了,可是,看看这代码,好像有重复冗余的部分,我们如何优化代码呢? 

答案是: 我们可以定义一个哨兵结点,这个结点可以不存放数据,让它指向新链表的头结点。 

    ListNode* node =(ListNode*) malloc(sizeof(ListNode));   //创建一个哨兵结点ListNode* newHead = node;                               //头结点指向哨兵结点ListNode* newTail = node;                               //尾结点指向哨兵结点

中间的循环也需要更改,不用判断链表是否为空了。

 while( l1 && l2){if(l1->val < l2->val){//       //l1比l2小// if(newTail == NULL){//      //如果链表为空//     newHead = newTail = l1;//  }else{//     //链表不为空//     newTail->next = l1;//     newTail = l1;//  }newTail->next = l1;newTail = l1;l1 = l1->next;        //l1指向下一个结点}else{//l2比l1小// if(newTail == NULL){//     //如果链表为空//     newHead = newTail = l2;//    }else{//     //链表不为空//      newTail->next = l2;//      newTail = l2;newTail->next = l2;newTail = l2;l2 = l2->next;      //l2指向下一个结点}
}

malloc了空间,但这块空间实际上用不了,最后我们需要将哨兵结点释放

    //malloc了空间,但这块空间实际上用不了,应该将其释放掉ListNode* ret = newHead->next;free(newHead);return ret; //返回头结点的下一个结点

好啦,优化过的代码如下:

 typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if(list1 == NULL){//如果list1为空,则返回list2return list2;}if(list2 == NULL){//如果list2为空,则返回list1return list1;}ListNode* l1 = list1;//定义l1变量,指向list1ListNode* l2 = list2; //定义l2变量,指向list2ListNode* node =(ListNode*) malloc(sizeof(ListNode));   //创建一个哨兵结点ListNode* newHead = node;                               //头结点指向哨兵结点ListNode* newTail = node;                               //尾结点指向哨兵结点while( l1 && l2){if(l1->val < l2->val){//       //l1比l2小// if(newTail == NULL){//      //如果链表为空//     newHead = newTail = l1;//  }else{//     //链表不为空//     newTail->next = l1;//     newTail = l1;//  }newTail->next = l1;newTail = l1;l1 = l1->next;        //l1指向下一个结点}else{//l2比l1小// if(newTail == NULL){//     //如果链表为空//     newHead = newTail = l2;//    }else{//     //链表不为空//      newTail->next = l2;//      newTail = l2;newTail->next = l2;newTail = l2;l2 = l2->next;      //l2指向下一个结点}
}//跳出循环存在两种情况,要么l1走到空l2不为空,要么l2走到空,l1不为空
//不可能存在都为空的情况if(l1){//l1没有遍历完链表newTail->next = l1;}if(l2){//l2没有遍历完链表newTail->next = l2;}//malloc了空间,但这块空间实际上用不了,应该将其释放掉ListNode* ret = newHead->next;free(newHead);return ret; //返回头结点的下一个结点
}

OK,今天的讲解到这里就结束啦,我们下期再见!

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

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

相关文章

使用DSP28335在CCS中生成正弦波

DSP芯片支持数学库&#xff0c;那如何通过DSP芯片生成一个正弦波呢&#xff1f;通过几天研究&#xff0c;现在将我的方法分享一下&#xff0c;如有错误&#xff0c;希望大家及时指出&#xff0c;共同进步。 sin函数的调用 首先看下一sin函数 的使用。 //头文件的定义 #includ…

OpenHarmony开发学习:【源码下载和编译】

本文介绍了如何下载鸿蒙系统源码&#xff0c;如何一次性配置可以编译三个目标平台&#xff08;Hi3516&#xff0c;Hi3518和Hi3861&#xff09;的编译环境&#xff0c;以及如何将源码编译为三个目标平台的二进制文件。 坑点总结&#xff1a; 下载源码基本上没有太多坑&#xff…

如何实现小程序滑动删除组件+全选批量删除组件

如何实现小程序滑动删除组件全选批量删除组件 一、简介 如何实现小程序滑动删除组件全选批量删除组件 采用 uni-app 实现&#xff0c;可以适用微信小程序、其他各种小程序以及 APP、Web等多个平台 具体实现步骤如下&#xff1a; 下载开发者工具 HbuilderX进入 【Dcloud 插…

部署GlusterFS群集

目录 一、部署GlusterFS群集 1. 服务器节点分配 2. 服务器环境&#xff08;所有node节点上操作&#xff09; 2.1 关闭防火墙 2.2 磁盘分区&#xff0c;并挂载 2.3 修改主机名&#xff0c;配置/etc/hosts文件 3. 安装、启动GlusterFS&#xff08;所有node节点上操作&…

Postman实现API自动化测试

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 关注公众号【互联网杂货铺】&#xff0c;回复 1 &#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 背景介绍 相信大部分开发人员和测试人员对 postman 都十分熟悉…

Python 爬虫基础——http请求和http响应

写本篇文章&#xff0c;我认为是能把自己所理解的内容分享出来&#xff0c;说不定就有和我一样有这样思维的共同者&#xff0c;希望本篇文章能帮助大家&#xff01;✨✨ 文章目录 一、 &#x1f308;python介绍和分析二、 &#x1f308;http请求三、 &#x1f308;http响应四、…

Day:005 | Python爬虫:高效数据抓取的编程技术(爬虫效率)

爬虫之多线程-了解 单线程爬虫的问题 因为爬虫多为IO密集型的程序&#xff0c;而IO处理速度并不是很快&#xff0c;因此速度不会太快如果IO卡顿&#xff0c;直接影响速度 解决方案 考虑使用多线程、多进程 原理&#xff1a; 爬虫使用多线程来处理网络请求&#xff0c;使用线程…

【Canvas技法】在Canvas按圆周绘制图形或是标注文字时,角度累加的方向为顺时针,起点为x轴正向

【图解说明】 【核心代码】 // 画圆弧及方向for(var i0;i<4;i){var startMath.PI/2*i;var endstartMath.PI/2;var x1180*Math.cos(start);var y1180*Math.sin(start);var x2180*Math.cos(end);var y2180*Math.sin(end);ctx.beginPath();ctx.arc(0,0,180,start,end,false);ct…

常见的解析漏洞总结

文件解析漏洞 文件解析漏洞主要由于网站管理员操作不当或者 Web 服务器自身的漏洞&#xff0c;导致一些特殊文件被 IIS、apache、nginx 或其他 Web服务器在某种情况下解释成脚本文件执行。 比如网站管理员配置不当&#xff0c;导致php2、phtml、ascx等等这些文件也被当成脚本文…

智慧公厕是什么?智慧公厕让“方便”更方便

智慧公厕是利用物联网、大数据、云计算、网络通信和自动化控制技术&#xff0c;将公共厕所实现信息化、智慧化和数字化使用与管理的一项创新举措。它建立了全面监测感知平台&#xff0c;通过实时监控公共厕所的运行状态&#xff0c;为管理单位提供高效的作业流程规划和安排&…

TPMD 程序:利用分子动力学轨迹研究速率过程并进行温度编程分子动力学计算的工具包

分享一篇使用分子动力学轨迹研究速率过程和执行温度程序化分子动力学计算的工具包&#xff1a;TPMD toolkit 。 感谢论文的原作者&#xff01; 主要内容 “ 以工具包的形式提供了分析分子动力学 (MD) 轨迹中的状态到状态转换所需的一组基本组件。该工具包可用于 (a) 确定系…

递归、搜索与回溯算法:⼆叉树中的深搜

⼆叉树中的深搜 深度优先遍历&#xff08;DFS&#xff0c;全称为 Depth First Traversal&#xff09;&#xff0c;是我们树或者图这样的数据结构中常⽤的 ⼀种遍历算法。这个算法会尽可能深的搜索树或者图的分⽀&#xff0c;直到⼀条路径上的所有节点都被遍历 完毕&#xff…

SpringBoot项目 jar包方式打包部署

SpringBoot项目 jar包方式打包部署 传统的Web应用进行打包部署&#xff0c;通常会打成war包形式&#xff0c;然后将War包部署到Tomcat等服务器中。 在Spring Boot项目在开发完成后&#xff0c;确实既支持打包成JAR文件也支持打包成WAR文件。然而&#xff0c;官方通常推荐将Sp…

【MATLAB源码-第6期】基于matlab的QPSK的误码率BER和误符号率SER仿真。

1、算法描述 QPSK&#xff0c;有时也称作四位元PSK、四相位PSK、4-PSK&#xff0c;在坐标图上看是圆上四个对称的点。通过四个相位&#xff0c;QPSK可以编码2位元符号。图中采用格雷码来达到最小位元错误率&#xff08;BER&#xff09; — 是BPSK的两倍. 这意味著可以在BPSK系统…

Java | Leetcode Java题解之第22题括号生成

题目&#xff1a; 题解&#xff1a; class Solution {static List<String> res new ArrayList<String>(); //记录答案 public List<String> generateParenthesis(int n) {res.clear();dfs(n, 0, 0, "");return res;}public void dfs(int n ,int…

阿里云函数计算 FC牵手通义灵码 ,打造智能编码新体验

通义灵码自成功入职阿里云后&#xff0c;其智能编程助手的角色除了服务于阿里云内部几万开发者&#xff0c;如今进一步服务函数计算 FC 产品开发者。近日&#xff0c;通义灵码正式进驻函数计算 FC WebIDE&#xff0c;让使用函数计算产品的开发者在其熟悉的云端集成开发环境中&a…

Nerf-Studio复现笔记

文章目录 1. Env2. Train3. Custom data3.1 Prepare3.2 Render and eval3.3 Results 4. Summary 1. Env The configuration process was smooth on Linux, but there are some problems with tiny_cuda_nn and colmap in Windows. // According to the installation document…

4.8QT

将按钮3&#xff0c;基于qt4版本连接实现点击按钮3&#xff0c;实现关闭窗口。 widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget), btn3(new QPushButton(this)) {ui->s…

MySQL数据库基础--索引

索引概述 索引是帮助MySQL高效获取数据的数据结构&#xff08;有序&#xff09; 优缺点 优势劣势提高数据检索的效率&#xff0c;降低数据库的IO成本索引列也是要占用空间的通过索引列对数据进行排序&#xff0c;降低数据排序的成本&#xff0c;降低CPU的消耗索引大大提高了查…

【数据库】PostgreSQL源码编译安装方式与简单配置(v16.2)

PostgreSQL源码编译安装方式与简单配置&#xff08;v16.2&#xff09; 一、PostgreSQL安装基本介绍1.1 几种PostgreSQL的安装方式1.2 删除原有的PostgreSQL1.3 编译安装过程简介 二、源码编译安装方式详情2.1 下载源代码2.2 编译安装运行 configure执行 make执行 make install …