删除链表元素相关的练习
目录
一、移除链表元素
二、删除排序链表中的重复元素
三、删除排序链表中的重复元素 ||
四、删除链表的倒数第 N 个结点
一、移除链表元素
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
示例 1:
输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
示例 2:
输入:head = [], val = 1
输出:[]
示例 3:
输入:head = [7,7,7,7], val = 7
输出:[]
提示:
-
列表中的节点数目在范围
[0, 10^4]
内 -
1 <= Node.val <= 50
-
0 <= val <= 50
代码实现一:
struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* pre = NULL;struct ListNode* cur = head;while (cur != NULL){if (cur->val == val){if (pre == NULL) // 当删除的是首元结点时,要做特殊处理,避免访问空指针{head = cur->next;free(cur);cur = head; // 切不可写成 cur = cur->next}else{pre->next = cur->next;free(cur);cur = pre->next; // 切不可写成 cur = cur->next}}else{pre = cur;cur = cur->next;}}return head;
}
free(cur); cur = cur->next
是一种类似刻舟求剑的典型的错误写法。
代码实现二:
struct ListNode* removeElements(struct ListNode* head, int val)
{struct ListNode* newhead = NULL;struct ListNode* tail = NULL;struct ListNode* cur = head;while (cur != NULL){if (cur->val != val){if (newhead == NULL) // 如果新链表为空{newhead = cur;tail = cur;}else{tail->next = cur;tail = cur;}cur = cur->next;}else{struct ListNode* tmp = cur;cur = cur->next;free(tmp);}}if (tail != NULL) // 避免对空指针的解引用{tail->next = NULL; }return newhead;
}
将值不是
val
的结点尾插到新链表中,由于尾插需要从头指针出发顺链找到尾结点,时间复杂度高,因此可以用一个尾指针tail
来记录并更新尾结点的位置。
图解示例一:
二、删除排序链表中的重复元素
给定一个已排序的链表的头 head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
示例 1:
输入:head = [1,1,2]
输出:[1,2]
示例 2:
输入:head = [1,1,2,3,3]
输出:[1,2,3]
提示:
-
链表中节点数目在范围
[0, 300]
内 -
-100 <= Node.val <= 100
-
题目数据保证链表已经按升序排列
代码实现:
struct ListNode* deleteDuplicates(struct ListNode* head)
{if (head == NULL) // 判断是否为空表{return NULL;}struct ListNode* tail = head;struct ListNode* cur = head->next;while (cur != NULL){if (cur->val != tail->val){// 尾插tail->next = cur;tail = cur;cur = cur->next;}else{// 删除重复的元素struct ListNode* tmp = cur;cur = cur->next;free(tmp);}}tail->next = NULL;return head;
}
三、删除排序链表中的重复元素 ||
给定一个已排序的链表的头 head
, 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。
示例 1:
输入:head = [1,2,3,3,4,4,5]
输出:[1,2,5]
示例 2:
输入:head = [1,1,1,2,3]
输出:[2,3]
提示:
-
链表中节点数目在范围
[0, 300]
内 -
-100 <= Node.val <= 100
-
题目数据保证链表已经按升序排列
代码实现:
struct ListNode* deleteDuplicates(struct ListNode* head)
{struct ListNode* newhead = NULL;struct ListNode* tail = NULL;struct ListNode* cur = head;while (cur != NULL){// 找到第一个值不同于 cur 的结点(也可能为空)struct ListNode* after = cur->next;while (after != NULL && after->val == cur->val){after = after->next;}// 判断 cur 是否属于有重复数字的结点if (cur->next == after) // 不属于{// 尾插if (newhead == NULL) // 如果新链表为空{newhead = tail = cur;}else{tail->next = cur;tail = cur;}cur = cur->next;}else // 属于{while (cur != after){struct ListNode* tmp = cur;cur = cur->next;free(tmp);}}}if (tail != NULL){tail->next = NULL;}return newhead;
}
四、删除链表的倒数第 N 个结点
给你一个链表,删除链表的倒数第 n
个结点,并且返回链表的头结点。
示例 1:
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]
提示:
-
链表中结点的数目为
sz
-
1 <= sz <= 30
-
0 <= Node.val <= 100
-
1 <= n <= sz
代码实现一:
struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{struct ListNode* pre_slow = NULL;struct ListNode* slow = head;struct ListNode* fast = head;while (--n){fast = fast->next; // 由于 1 <= n <= sz,所以 fast 不可能走到空}while (fast->next != NULL){pre_slow = slow;slow = slow->next;fast = fast->next;}if (pre_slow == NULL){head = slow->next;free(slow);}else{pre_slow->next = slow->next;free(slow);}return head;
}
相关练习:链表的中间结点、链表中倒数第 k 个结点
代码实现二:
struct ListNode* removeNthFromEnd(struct ListNode* head, int n)
{// 设置一个哨兵位的头结点struct ListNode* guard = (struct ListNode*)malloc(sizeof(struct ListNode));guard->next = head;// 计算链表的长度(包括头结点)int len = 0;struct ListNode* cur = guard;while (cur != NULL){++len;cur = cur->next;}// 找到倒数第 n + 1 个结点(可能是 guard)struct ListNode* pre = guard;for (int i = 0; i < len - n - 1; ++i){pre = pre->next;}// 删除倒数第 n 个结点struct ListNode* tmp = pre->next;pre->next = tmp->next;free(tmp);// 删除哨兵位的头结点并返回 headhead = guard->next;free(guard);return head;
}
设置哨兵位的头结点的好处是便于首元结点的处理。
相关文章:

删除链表元素相关的练习
目录 一、移除链表元素 二、删除排序链表中的重复元素 三、删除排序链表中的重复元素 || 四、删除链表的倒数第 N 个结点 一、移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val val 的节点,并返回 新的头…...

3DEXPERIENCE Works 成为了中科赛凌实现科技克隆环境的催化剂
您的企业是否想过实现设计数据的统筹管理,在设计上实现标准化,并把每位设计工程师串联起来协同办公?中科赛凌通过使用3DEXPERIENCE Works 实现了上述内容,一起来看本期案例分享吧!中科赛凌 通过其自主研发的单压缩机制冷技术实现零下190℃制…...

少儿编程 电子学会图形化编程等级考试Scratch一级真题解析(选择题)2022年12月
少儿编程 电子学会图形化编程等级考试Scratch一级真题解析2022年12月 选择题(共25题,每题2分,共50分) 1、小明想在开始表演之前向大家问好并做自我介绍,应运行下列哪个程序 A、 B、 C、 D、 答案:D...

【完整版】国内网络编译,Ambari 2.7.6 全部模块源码编译笔记
本次编译 ambari 2.7.6 没有使用科学上网的工具,使用的普通网络,可以编译成功,过程比 ambari 2.7.5 编译时要顺畅。 以下是笔记完整版。如果想单独查看本篇编译笔记,可参考:《Ambari 2.7.6 全部模块源码编译笔记》 该版本相对 2.7.5 版本以来,共有 26 个 contributors …...
HTML 颜色值
HTML 颜色值 颜色由红 (R)、绿 (G)、蓝 (B) 组成。 颜色值 颜色值由十六进制来表示红、绿、蓝(RGB)。 每个颜色的最低值为 0 (十六进制为 00 ),最高值为 255 (十六进制为 FF )。 十六进制值的写法为#号后跟三个或六个十六进制字符。 三位…...
RabbitMQ-消息的可靠性投递
文章目录0. 什么是消息的可靠性投递1. confirm机制2. return机制3. 总结0. 什么是消息的可靠性投递 在生产环境中,如果因为一些不明原因导致RabbitMQ重启,RabbitMQ重启过程中是无法接收消息的,那么我们就需要生产者重新发送消息。或者在消息…...
华为OD机试题 - 最小叶子节点(JavaScript)| 含思路
华为OD机试题 最近更新的博客使用说明本篇题解:最小叶子节点题目输入输出示例一输入输出示例二输入输出Code解题思路华为OD其它语言版本最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD…...
嵌入式系统硬件设计与实践(开发过程)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 如果把电路设计看成是画板子的,这本身其实是狭隘了。嵌入式硬件设计其实是嵌入式系统中很重要的一个部分。里面软件做的什么样…...

入门vue(1-10)
正确学习方式:视频->动手实操->压缩提取->记录表述 1基础结构 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"&…...
C#开发的OpenRA的游戏主界面怎么样创建3
继续游戏主界面创建的主题, 我们知道游戏的主界面上有很多部件,比如显示文本的标签(LabelWidget), 显示按钮(ButtonWidget)。那么这些部件又是如何创建在主界面上的呢? 其实这些部件是否显示,都是来源于文件yaml,在这里就是文件mainmenu.yaml, 在这个文件里定义了所有…...

秒懂算法 | 基于主成分分析法、随机森林算法和SVM算法的人脸识别问题
本文的任务与手写数字识别非常相似,都是基于图片的多分类任务,也都是有监督的。 01、数据集介绍与分析 ORL人脸数据集共包含40个不同人的400张图像,是在1992年4月至1994年4月期间由英国剑桥的Olivetti研究实验室创建。 此数据集下包含40个目录,每个目录下有10张图像,每个…...

QML Loader(加载程序)
Loader加载器用于动态加载 QML 组件。加载程序可以加载 QML 文件(使用 source 属性)或组件对象(使用 sourceComponent 属性) 常用属性: active 活动asynchronous异步,默认为falseitem项目progress 进度so…...

C++——类型转换
目录 C语言中的类型转换 C强制类型转换 static_cast reinterpret_cast const_cast dynamic_cast 延伸问题 RTTI(了解) C语言中的类型转换 在C语言中,如果赋值运算符左右两侧类型不同,或者形参与实参类型不匹配,或…...

vue3:生命周期(onErrorCaptured)
一、背景 当项目如果发生报错,影响程序体验。如果能以捕获的方式得到错误信息,而且还能定位问题,这样就好了,本文介绍onErrorCaptured实现我们想要的效果。 vue2:errorCaptured。使用与vue3同理。 vue3:…...
vue过滤器
vue 过滤器 对要显示的数据进行特定格式化之后再显示 注册过滤器 Vue.filter(name,callback)new Vue({filters:{}}) 使用过滤器 {{ name | 过滤器名 }}v-band:属性“name | 过滤器名” 局部过滤器 <p>{{time | timeFormater }}</p> <!-- 过滤器可接受额外参…...

I/O模型
写在前面 前面聊完了IO方式, 也就意味着网络数据的收发通道是建立起来了。但业务场景中, 通道本身是不会发送数据的。在常见的网络应用中, server端会创建多个链接以服务更多client, 同时要求各个client尽可能互不影响。这是I/O模型(也就是IO方式线程模型)要解决的问题。由于加…...

前端必备技术之——AJAX
简介 AJAX 全称为 Asynchronous JavaScript And XML,就是异步的 JS 和 XML(现在已经基本被json取代)。通过 AJAX 可以在浏览器中向服务器发送异步请求,最大的优势:无刷新获取数据。AJAX 不是新的编程语言,而是一种将现有的标准组…...
MySQL数据库 各种指令操作大杂烩(DML增删改、DQL查询、SQL...)
文章目录前言一、DML 增删改添加数据修改数据删除数据二、DQL 查询基本查询条件查询聚合函数(count、max、min、avg、sum)分组查询(group by)排序查询(order by)分页查询(limit)DQL 语句练习三、SQLDCL 权限控制约束案例多表查询事务存储引擎字符串函数数值函数日期函数流程函数…...

Java分布式全局ID(一)
随着互联网的不断发展,互联网企业的业务在飞速变化,推动着系统架构也在不断地发生变化。 如今微服务技术越来越成熟,很多企业都采用微服务架构来支撑内部及对外的业务,尤其是在高 并发大流量的电商业务场景下,微服务…...

算法分析与设计之并查集详解
算法分析与设计之并查集1.前言2.并查集的基础2.1.关于动态连通性2.2.动态连通性的应用场景:2.3.对问题建模:2.4.建模思路:2.5.API2.7.Quick-Find算法:2.8.Quick-Union算法:3. 并查集的应用1.前言 本文主要介绍解决动态…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

阿里云ACP云计算备考笔记 (5)——弹性伸缩
目录 第一章 概述 第二章 弹性伸缩简介 1、弹性伸缩 2、垂直伸缩 3、优势 4、应用场景 ① 无规律的业务量波动 ② 有规律的业务量波动 ③ 无明显业务量波动 ④ 混合型业务 ⑤ 消息通知 ⑥ 生命周期挂钩 ⑦ 自定义方式 ⑧ 滚的升级 5、使用限制 第三章 主要定义 …...

【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...
unix/linux,sudo,其发展历程详细时间线、由来、历史背景
sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...

嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...

搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...