链表|反转链表|移除链表元素|链表的中间节点|返回倒数第k个节点|合并两个有序链表(C)

206. 反转链表


![[Pasted image 20241025215801.png]]

用两个指针
![[Pasted image 20241025215926.png]]

p1指向空,p2指向第一个节点
![[Pasted image 20241025220000.png]]

p2的next指向p1,把方向调过来

因为p2的next指向p1,会丢掉后面的节点,所以需要三个节点
前两个指针是为了反转,后一个指针是为了找到下一个节点
![[Pasted image 20241025220955.png]]

p2给给p1,p3给给p2,p3指向下一个
![[Pasted image 20241025221026.png]]

![[Pasted image 20241025221110.png]]

![[Pasted image 20241025221130.png]]

p2指向NULL,循环结束
![[Pasted image 20241025221257.png]]

最后p1指向的就是链表的头

struct ListNode* reverseList(struct ListNode* head) {struct ListNode* p1, *p2, *p3;p1 = NULL;p2 = head;if (p2)p3 = p2->next;while (p2){p2->next = p1;p1 = p2;p2 = p3;if (p3)p3 = p3->next;}return p1;
}
  • 开始需要判断p2是否为空,如果p2为空,直接返回p1
  • 循环的时候需要判断p3是否为空,如果p3为空,就不需要再往后走了
思路2

头插法
![[Pasted image 20241027154804.png]]

创建一个newhead指针,一开始指向NULL,从上面的节点下来头插即可
![[Pasted image 20241027154944.png]]

用next保存cur的下一个,将cur的next指向newhead,newhead指向cur
![[Pasted image 20241027155048.png]]

再把next给给cur,next继续往下走
![[Pasted image 20241027155145.png]]

继续头插,把cur的next指向newhead
![[Pasted image 20241027155212.png]]

cur给给newhead
![[Pasted image 20241027155301.png]]

next给给cur,next继续往后遍历,直到cur为空结束

struct ListNode* reverseList(struct ListNode* head) {struct ListNode* cur = head;struct ListNode* newhead = NULL;while (cur){struct ListNode* next = cur->next;cur->next = newhead;newhead = cur;cur = next;}return newhead;
}

203. 移除链表元素


删除所有值等于val的节点
通过cur指针遍历链表中的节点,遍历的过程中,用prev指针记录cur的前一个节点
![[Pasted image 20241026134640.png]]

将prev的next指向cur的next,再删除cur
![[Pasted image 20241026134757.png]]

![[Pasted image 20241026134809.png]]

再把cur往后挪
![[Pasted image 20241026134823.png]]

直到cur指向NULL,遍历结束

如果需要处理头节点,套入循环内会比较麻烦

struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* prev = NULL, *cur = head;while (cur){if (cur->val == val){//删除if (cur == head)   //如果头节点需要删除,将cur往后挪,直接删除头节点{head = cur->next;free(cur);cur = head;}else{prev->next = cur->next;free(cur);cur = prev->next;}}else{prev = cur;cur = cur->next;}}return head;
}
思路2

遍历原链表,把不是val的节点,尾插到新链表
![[Pasted image 20241026142211.png]]

需要用next指针找下一个节点,否则删除了cur,链表会断开
这时候往新链表尾插,时间复杂度会提高,因为需要找尾
只要创建一个tail指针,这样就不需要找尾
![[Pasted image 20241026142645.png]]

当头节点需要删除时,直接往后遍历,直接删除头节点

struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* cur = head;struct ListNode* newhead = NULL, * tail = NULL;while (cur){if (cur->val == val){struct ListNode* del = cur;cur = cur->next;free(del);}else{if (tail == NULL){newhead = tail = cur;}else{tail->next = cur;tail = tail->next;}cur = cur->next;}}if (tail)tail->next = NULL;return newhead;
}

最后将一个不为val的节点,尾插到新链表,但是这个节点的next还是指向原链表的下一个节点,如果这个下一个节点不是要删除的,继续往后尾插就ok,如果下一个节点要删除,这个尾插到新链表的节点指向的就不是空
但是不能每次尾插之后,把tail的next置为NULL,这样cur会指向空,不能往后遍历

要在循环结束后,给tail的next置空。
这时候如果head是空,cur就是空,循环就不会进去,newhead和tail就是空。
所以需要判断tail是否为空

876. 链表的中间结点


![[Pasted image 20241026194539.png]]

若链表中的节点数是奇数个,返回中间的那一个
若链表中的节点数是偶数个,返回中间两个的第二个

思路1

先遍历一遍,算长度,再遍历一遍,找到中间的节点

思路2

快慢指针
定义一个慢指针,和快指针,慢指针一次走一步,快指针一次走两步,快指针走到结尾的时候,慢指针走的是快指针的一半,恰好就在链表的中间
奇数个
![[Pasted image 20241026194944.png]]

![[Pasted image 20241026195003.png]]

![[Pasted image 20241026195034.png]]

偶数个
![[Pasted image 20241026195116.png]]

![[Pasted image 20241026195129.png]]

![[Pasted image 20241026195202.png]]

![[Pasted image 20241026195215.png]]

struct ListNode* middleNode(struct ListNode* head) {struct ListNode* slow = head, *fast = head;while (fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;
}

面试题 02.02. 返回倒数第 k 个节点


快指针先走k步,然后再同时走,走到fast为NULL结束,slow就是倒数第k个
![[Pasted image 20241027091517.png]]

k=3
![[Pasted image 20241027091536.png]]

fast先走3步,之后同时走
![[Pasted image 20241027091615.png]]

当fast指向NULL时,slow指向倒数第3个

int kthToLast(struct ListNode* head, int k) {struct ListNode* slow = head;struct ListNode* fast = head;for (k--){//链表没有k步长,倒数第k个就算是空if (fast == NULL){return NULL;}fast = fast->next;}while (fast){fast = fast->next;slow = slow->next;}return slow->val;
}

k–,走k次
–k,走k-1次

21. 合并两个有序链表


取小的尾插
用两个指针list1和list2分别遍历两个有序链表
为了方便尾插定义两个指针head和tail,一开始都是空
尾插时,将tail给给tail的next,list2还是给给list2的next继续往后遍历
![[Pasted image 20241026220442.png]]

取小的尾插,list2往后走
![[Pasted image 20241026220819.png]]

取小的尾插,list1往后走
![[Pasted image 20241026221710.png]]

tail的next赋给tail
![[Pasted image 20241027091215.png]]

如果有一个list指针指向空,就结束了,剩下一个链表,直接连接到后面

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if (list1 == NULL)return list2;if (list2 == NULL)return list1;struct ListNode* head = NULL, *tail = NULL;while (list1 && list2){if (list1->val < list2->val){if (tail == NULL){head = tail = list1;}else{tail->next = list1;tail = tail->next;}list1 = list1->next;}else{if (tail == NULL){head = tail = list2;}else{tail->next = list2;tail = tail->next;}list2 = list2->next;}}if (list1){tail->next = list1;}if (list2){tail->next = list2;}return head;
}
思路2

加入哨兵位,方便尾插,最后把哨兵位free掉

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if (list1 == NULL)return list2;if (list2 == NULL)return list1;struct ListNode* head = NULL, *tail = NULL;head = tail = (struct ListNode*)malloc(sizeof(struct ListNode));while (list1 && list2){if (list1->val < list2->val){tail->next = list1;tail = tail->next;list1 = list1->next;}else{tail->next = list2;tail = tail->next;list2 = list2->next;}}if (list1){tail->next = list1;}if (list2){tail->next = list2;}struct ListNode* del = head;head = head->next;free(del);return head;
}

这样尾插的时候可以不用判断tail是否为空

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

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

相关文章

GitGraphPro 图管理系统

1.产品介绍 产品介绍方案 产品名称: GitGraphPro 图管理系统 主要功能: 智能图谱构建版本控制与协作数据分析与可视化自定义模板与导出功能介绍: 1. 智能图谱构建 具体作用:GitGraphPro 利用先进的算法,自动从项目数据

一:时序数据库-Influx应用

目录 0、版本号 1、登录页面 2、账号基本信息 3、数据库案例 4、可视化 5、java案例 0、版本号 InfluxDB v2.4.0 1、登录页面 http://127.0.0.1:8086/signin 账号&#xff1a;自己账号 密码&#xff1a;自己密码 2、账号基本信息 查看用户id和组织id&#xff01;&…

python脚本:十六进制数据小端序转大端序

大多数机器的存储方式都是小端排序&#xff0c;小端序指的是数据的高位&#xff08;偏左边的&#xff09;放在内存中的高地址&#xff08;偏右边的&#xff09;处&#xff0c;这样会导致存放好的数据对于我们看来好像是“倒过来”的 大端序则是我们看上去从左到右的正常排序 例…

流场主动流动控制

对于流场的主动控制而言&#xff0c;其难点主要集中在强化学习的环境搭建过程&#xff0c;如何建立数值仿真与强化学习的信息交互是研究过程中的拦路虎。经过几个星期的研究&#xff0c;已基本实现由pycharm程序数据端向star ccm端的数据传递。其主要过程包括如下过程&#xff…

Django-文件上传

定义&#xff1a; 上传规则-前端【html】&#xff1a; 上传规则-后端【Django】&#xff1a; urlpatterns [path(upload,views.test_upload) ] 例子&#xff1a; settings添加: MEDIA_URL /media/ MEDIA_ROOT os.path.join(BASE_DIR, media) 主路由&#xff1a; urlpa…

kafka-console-ui的简介及安装使用

kafka-console-ui的简介及安装使用 一、kafka-console-ui的简介二、安装kafka-console-ui2.1 源码安装2.2 docker安装 三、kafka-console-ui功能使用3.1、功能特性3.2、 功能介绍3.2.1 集群3.2.2 topic3.2.3 消费组3.2.4 Acl3.2.5 运维 一、kafka-console-ui的简介 kafka-cons…

ONLYOFFICE 8.2 版本产品评测——遥遥领先

知孤云出岫-CSDN博客 目录 产品介绍——篇【1】 一.关于 ONLYOFFICE 桌面编辑器 二.关于 ONLYOFFICE 协作空间 三.关于 ONLYOFFICE 文档 四.关于 ONLYOFFICE的版本介绍 产品新功能——篇【2】 一.关于 ONLYOFFICE的新增功能介绍 二.OLE FICE文档概述 三.PDF编辑器更新 …

星河飞雪网络安全学习笔记-shodan使用7(完结)

学习笔记-shodan使用7 Shodan命令 info shodan info查询账户搜索次数。 Domain shodan domain baidu.com查询ip域名信息 Scan shodan scan submit ip对ip进行实时扫描&#xff0c;类似nmap。 shodan scan list显示扫描信息。 Stats shodan stats --facets ssl.version countr…

【原创分享】详述中间件的前世今生

中间件是一种软件组件&#xff0c;位于应用程序和操作系统之间&#xff0c;通过提供统一的接口和功能来简化开发和管理应用程序、提高应用程序的可靠性和性能。 中间件的前世可以追溯到20世纪80年代的分布式系统和网络技术的发展。在那个时候&#xff0c;随着计算机网络的普及…

Python | Leetcode Python题解之第524题通过删除字母匹配到字典里最长单词

题目&#xff1a; 题解&#xff1a; class Solution:def findLongestWord(self, s: str, dictionary: List[str]) -> str:m len(s)f [[0] * 26 for _ in range(m)]f.append([m] * 26)for i in range(m - 1, -1, -1):for j in range(26):if ord(s[i]) j 97:f[i][j] iel…

论文翻译 | PROMPTAGATOR : FEW-SHOT DENSE RETRIEVAL FROM 8 EXAMPLES

摘要 最近的信息检索研究主要集中在如何从一个任务&#xff08;通常有丰富的监督数据&#xff09;转移到其他各种监督有限的任务上&#xff0c;其隐含的假设是从一个任务可以泛化到所有其他任务。然而&#xff0c;这忽略了这样一个事实&#xff0c;即存在许多多样化和独特的检索…

AIGC时代的网络威胁和防御

AIGC时代的网络威胁和防御 1. 生成式AI是否将成为网络威胁者的战术新宠&#xff1f;​论文地址​研究背景​主要贡献​攻击方法​示例​研究结论​ 2. LLM Honeypot: 利用大型语言模型打造先进的交互式蜜罐系统​论文地址​一、研究背景​二、研究方法​&#xff08;一&#xf…

mysql中的锁理解

1.共享锁&#xff0c;排他锁&#xff0c;也叫读锁和写锁 共享锁(S锁)(读锁)&#xff1a;事务在读取记录的时候获取共享锁&#xff0c;允许其它事务同时获取共享锁。 排他锁(X锁)(写锁)&#xff1a;事务在修改记录的时候获取排他锁&#xff0c;只允许一个事务获取排他锁&#x…

聚水潭数据集成到MySQL的技术实操与解决方案

聚水潭数据集成到MySQL的技术案例分享 在现代企业的数据管理过程中&#xff0c;如何高效、可靠地实现不同系统之间的数据对接是一个关键问题。本案例将聚焦于“聚水谭-仓库查询单-->BI邦盈-仓库表”的数据集成方案&#xff0c;详细探讨如何通过轻易云数据集成平台&#xff…

鸿蒙系统的优势 不足以及兼容性与未来发展前景分析

2024 年 10 月 22 日&#xff1a;华为正式发布原生鸿蒙操作系统 HarmonyOS next&#xff0c;并正式命名为 HarmonyOS 5&#xff0c;这是鸿蒙系统史上最大的升级&#xff0c;实现了国产操作系统从底层架构到应用生态的全面自主可控。 鸿蒙系统与安卓、iOS 相比&#xff0c;具有…

C++:哈希表

目录 哈希的概念 直接定址法 哈希冲突 负载因子 哈希函数 除法散列法/除留余数法 乘法散列法 处理哈希冲突 开放定址法 线性探测 二次探测 双重散列 链地址法 哈希表的实现 哈希表的结构 闭散列&#xff08;开放定址法&#xff09; 结构 插入 查找 删除 …

Java系统学习笔记

计算机知识 CMD 环境变量 想要在任意目录下都可以打开指定的软件&#xff0c;就可以把软件的路径配置到环境变量中。 JDK JDK安装目录中 javac 是JDK提供的一个工具&#xff0c;可以通过这个工具&#xff0c;把java文件编译成class文件 java 也是JDK提供的一个工具&#xf…

C语言部分输入输出(printf函数与scanf函数,getchar与putchar详解,使用Linux ubuntu)

1.输入输出 1.1.按格式输入输出 printf 可以在man手册中查看 int printf(const char *format, ...); printf:函数名(参数)int:函数的返回值 功能&#xff1a;按格式在终端输出 参数&#xff1a;多参 返回值&#xff1a;输出字符个数 格式&#xff1a; %d int %c char…

WPF+MVVM案例实战(十五)- 实现一个下拉式菜单(上)

文章目录 1 案例效果2、图标资源下载3、功能实现1.文件创建2、菜单原理分析3、一级菜单两种样式实现1、一级菜单无子项样式实现2、一级菜单有子项样式实现 4、总结 1 案例效果 提示 2、图标资源下载 从阿里矢量素材官网下载需要的菜单图片&#xff0c;如下所示&#xff1a; …

Python 从入门到实战43(Pandas数据结构)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;可以熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们学习了NumPy数组操作的相关基础知识。今天学习一下pa…