Ieetcode——21.合并两个有序链表

ops/2024/10/19 9:40:23/

21. 合并两个有序链表 - 力扣(LeetCode)

合并两个有序链表我们的思路是创建一个新链表,然后遍历已知的两个有序链表,并比较其节点的val值,将小的尾插到新链表中,然后继续遍历,直到将该两个链表的全部节点全部尾插到新链表中。下面我来画图分析一下如何进行遍历和尾插:

遍历和尾插的过程就如上图一般,接下来我们来实现代码。

我们在写代码的时候还应该注意一些特殊情况:有序链表为空的情况。 

我们看,对于这两种情况下:如果两个有序链表都为空,那么就返回NULL;如果只有一个为空,那就返回另外一个。 

分析到这里,我们就可以开始写代码了。(注意:该代码只包含解决该问题的函数部分,不包含主函数内容)

typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{//有空链表if(list1 == NULL){return list2;}if(list2 == NULL){return list1;}//无空链表//创建新链表,遍历两链表ListNode* newlist = NULL;ListNode* newtail = NULL;while(list1 && list2)//这两个链表只要有一个走到了NULL,就说明为NULL的链表已经全部尾插完了{if(list1->val <= list2->val){if(newlist == NULL){//新链表为空newlist = list1;newtail = list2;}else{//新链表不为空newtail->next = list1;newtail = newtail->next;}//尾插完后,遍历下一个节点list1 = list1->next;}else{if(newlist == NULL){//新链表为空newlist = list1;newtail = list2;}else{//新链表不为空newtail->next = list1;newtail = newtail->next;}//尾插完后遍历下一个节点list2 = list2->next;}}//跳出循环,说明有一个链表已经遍历完了,只需将另一个链表的剩余元素尾插到新链表if(list1 == NULL){//list1遍历完了,将list2尾插到新链表中newtail->next = list2;}else{//list2遍历完了,将list1尾插到新链表中newtail->next = list1;}return newlist;
}

我们写完之后,代码虽然可以成功解决问题,但是其中出现了很多重复的代码。 

哨兵位是一个有空间但是没有值的节点,而且是动态开辟的内存空间,所以我们现在就不能直接返回newist了,而是返回newlist->next,但是动态开辟的内存空间我们使用完之后就应该释放掉,所以我们应该先创建一个临时变量将newist->next存起来,然后将newlist释放掉,后返回临时变量。

所以我们要对该代码进行两部分的调整:

部分一:用来解决重复代码

部分二:用来解决动态内存开辟的释放以及哨兵位的引入对返回值的影响 

下面附上完整代码:

typedef struct ListNode ListNode;//避免因为类型名长而对其进行重命名
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{//有空链表if(list1 == NULL){return list2;}if(list2 == NULL){return list1;}//无空链表//创建新链表,遍历两链表ListNode* newlist = (ListNode*)malloc(sizeof(ListNode));ListNode* newtail = newlist;while(list1 && list2)//这两个链表只要有一个走到了NULL,就说明为NULL的链表已经全部尾插完了{if(list1->val <= list2->val){newtail->next = list1;newtail = newtail->next;//尾插完后,遍历下一个节点list1 = list1->next;}else{newtail ->next = list2;newtail = newtail->next;//尾插完后遍历下一个节点list2 = list2->next;}}//跳出循环,说明有一个链表已经遍历完了,只需将另一个链表的剩余元素尾插到新链表if(list1 == NULL){//list1遍历完了,将list2尾插到新链表中newtail->next = list2;}else{//list2遍历完了,将list1尾插到新链表中newtail->next = list1;}ListNode* ret = newlist->next;free(newlist);newlist = NULL;return ret;
}

 完!


http://www.ppmy.cn/ops/25302.html

相关文章

【C/C++】动态内存管理(C:malloc,realloc,calloc,free || C++:new,delete)

&#x1f525;个人主页&#xff1a; Forcible Bug Maker &#x1f525;专栏&#xff1a; C | | C语言 目录 前言C/C内存分布C语言中的动态内存管理&#xff1a;malloc/realloc/realloc/freemallocrealloccallocfree C中的动态内存管理&#xff1a;new/deletenew和delete操作内…

商城数据库88张表结构(八)

DDL 29.商品规格表 CREATE TABLE wang_goods_specs (id int(11) NOT NULL AUTO_INCREMENT COMMENT 自增ID,shopId int(11) NOT NULL DEFAULT 0 COMMENT 店铺ID,goodsid int(11) NOT NULL DEFAULT 0 COMMENT 商品ID,productNo varchar(20) NOT NULL COMMENT 商品货号,specids v…

C语言:插入排序

插入排序 1.解释2.步骤3.举例分析示例结果分析 1.解释 插入排序是一种简单直观的排序算法&#xff0c;它的工作原理是通过构建有序序列&#xff0c;对于未排序数据&#xff0c;在已排序序列中从后向前扫描&#xff0c;找到相应位置并插入。插入排序在实现上&#xff0c;通常采…

【C++】手撕list(list的模拟实现)

目录 01.节点 02.迭代器 迭代器运算符重载 03.list类 &#xff08;1&#xff09;构造与析构 &#xff08;2&#xff09;迭代器相关 &#xff08;3&#xff09;容量相关 &#xff08;4&#xff09;访问操作 &#xff08;5&#xff09;插入删除 我们在学习数据结构的时候…

程序员商业模式画布

首先&#xff0c;我们来关注价值主张。这个提议的核心理念是减轻那些认为学习是痛苦过程的人的困扰&#xff0c;给他们一点激励&#xff0c;好让他们能够持续、轻松地学习。 我们的目标是通过为学习过程增添乐趣&#xff0c;来缓解那些不太愿意学习的人的痛苦感&#xff0c;从…

一种基于YOLOv8改进的高精度红外小目标检测算法 (原创自研)

&#x1f4a1;&#x1f4a1;&#x1f4a1;本文摘要&#xff1a;一种基于YOLOv8改进的高精度小目标检测算法&#xff0c; 在红外小目标检测任务中实现暴力涨点&#xff1b; &#x1f4a1;&#x1f4a1;&#x1f4a1;创新点&#xff1a; 1&#xff09;SPD-Conv特别是在处理低分…

Linux--MyMiniTry--Vim

首先下载好vim,我们可以按以下的方式进行光标的移动&#xff08;也可以回车进行换行&#xff09; &#xff08;--> 进入教程&#xff09; &#xff08;初始的时候没有文本&#xff0c;你怎么按都没有用&#xff09; &#xff08;我们要先按 i &#xff0c;进行插入文本才…

C语言实验-函数与模块化程序设计

一&#xff1a; 编写函数fun&#xff0c;其功能是&#xff1a;输入一个正整数&#xff0c;将其每一位上为偶数的数取出重新构成一个新数并输出。主函数负责输入输出&#xff0c;如输入87653142&#xff0c;则输出8642。&#xff08;main函数->fun函数&#xff09; #define _…