LeetCode.203移除链表元素(原链表操作、虚拟头结点)

LeetCode.203移除链表元素

  • 1.问题描述
  • 2.解题思路
  • 3.代码

1.问题描述

给你一个链表的头节点 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, 104]
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

2.解题思路

以链表 1 4 2 4 来举例,移除元素4。

如果使用C,C++编程语言的话,不要忘了还要从内存中删除这两个移除的节点, 清理节点内存之后如图:

当然如果使用java ,python的话就不用手动管理内存了。(就算使用C++来做leetcode,如果移除一个节点之后,没有手动在内存中删除这个节点,leetcode依然也是可以通过的,只不过,内存使用的空间大一些而已,但建议依然要养成手动清理内存的习惯。)

那么:上述例子中,删除第一个4,只要将1的next指针直接指向下下个节点就好了。但这样,如果删除的是头结点就不好办了,于是两个办法。

  1. 直接使用原来的链表来进行删除操作。

    其余节点:用上述法子便行

    头结点:移除头结点和移除其他节点的操作是不一样的,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。

    所以只要将头结点向后移动一位就可以,这样就从链表中移除了一个头结点。依然别忘将原头结点从内存中删掉。

  2. 设置一个虚拟头结点在进行删除操作。

    这里来给链表添加一个虚拟头结点为新的头结点,此时要移除这个旧头结点元素1。就和移除链表其他节点的方式统一了。最后return 头结点的时候,别忘了 return dummyNode->next;, 这才是新的头结点

3.代码

C++:直接使用原来的链表来进行删除操作

#include <iostream>
#include <vector>
using namespace std;struct ListNode {int val;ListNode* next;ListNode(int x): val(x), next(NULL) {}
};class Solution {public:ListNode* removeElements(ListNode* head, int val) {// 删除头结点值等于val的节点//为什么不用if,因为若输入为head = [1,1,1,1,1],应为一个持续移除的过程,所以为while//头结点不能为空,如果为空,相当于操作空指针了while(head != NULL && head->val == val) {//创建了一个临时指针tmp,它指向链表的头结点head。//这是为了保存需要被删除的节点,以便在将指针从链表中删除时,能够释放该节点所占用的内存。ListNode* tmp = head;head = head->next;delete tmp;  }ListNode* cur = head;//cur != NULL: 确保当前节点不为空。在删除节点时,我们需要更改节点的指针来连接正确的节点,//所以我们要确保cur指针不为空,避免访问空指针导致程序崩溃。//cur->next != NULL: 确保当前节点的下一个节点不为空。在删除节点时,//我们需要访问当前节点的下一个节点的值来进行比较,如果下一个节点为空,//则没有必要进行比较和删除操作while(cur != NULL && cur -> next != NULL) {if(cur->next->val == val) {ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;} else {cur = cur->next;}}return head;}
};int main() {    vector<int> nums = {1, 2, 6, 3, 4, 5, 6}; // 用数组存储链表节点的值    ListNode* head = NULL; // 链表的头节点初始化为NULL    // 将数组的值转换为链表节点并加入到链表中  for(int i = 0; i < nums.size(); i++) {   ListNode* node = new ListNode(nums[i]);    if (head == NULL) {  head = node; // 如果链表为空,则新节点即为头节点  } else {  ListNode* temp = head;  while(temp->next != NULL) {  temp = temp->next;  }  temp->next = node; // 将新节点添加到链表末尾  }  }    Solution solve;    head = solve.removeElements(head, 6); // 删除值为6的节点  // 输出新链表的值  ListNode* current = head;  while(current != NULL) {   cout << current->val << " ";    current = current->next;    }    return 0;    
}

C++:虚拟头结点

#include <iostream>
#include <vector>
using namespace std;struct ListNode {int val;ListNode* next;ListNode(int x): val(x), next(NULL) {}//构造函数
};class Solution {public:ListNode* removeElements(ListNode* head, int val) {ListNode* dummyHead = new ListNode(0);//创建虚拟头节点dummyHead->next = head;//虚拟头节点指向头节点//临时指针从虚拟头节点开始遍历,如果直接用头结点进行遍历,那么头结点所指向的值是一直在改变的,最后无法返回了ListNode* cur = dummyHead;while(cur->next != NULL) {if(cur->next->val == val) {ListNode* tmp = cur->next;//暂存要删除的节点cur->next = cur->next->next;//删除节点delete tmp;//释放内存} else {cur = cur->next;//指向下一个节点}}head = dummyHead->next;//更新头节点  因为旧的head可能已经被删除了delete dummyHead;//释放虚拟头节点内存return head;//返回头节点}
};int main() {    vector<int> nums = {1, 2, 6, 3, 4, 5, 6}; // 用数组存储链表节点的值    ListNode* head = NULL; // 链表的头节点初始化为NULL    // 将数组的值转换为链表节点并加入到链表中  for(int i = 0; i < nums.size(); i++) {   ListNode* node = new ListNode(nums[i]);    if (head == NULL) {  head = node; // 如果链表为空,则新节点即为头节点  } else {  ListNode* temp = head;  while(temp->next != NULL) {  temp = temp->next;  }  temp->next = node; // 将新节点添加到链表末尾  }  }    Solution solve;    head = solve.removeElements(head, 6); // 删除值为6的节点  // 输出新链表的值  ListNode* current = head;  while(current != NULL) {   cout << current->val << " ";    current = current->next;    }    return 0;    
}

python:虚拟头结点

class ListNode:def __init__(self, val, next=None):self.val = valself.next = nextclass Solution:def removeElements(self, head: ListNode, val: int) -> ListNode:dummyHead = ListNode()dummyHead.next = headcur = dummyHeadwhile cur.next:if cur.next.val == val:cur.next = cur.next.nextelse:cur = cur.nextreturn dummyHead.nextvalues = [1, 2, 6, 3, 4, 5, 6]# 使用循环构造链表
dummy = ListNode(0)  # 创建一个虚拟头节点以简化边界情况处理
current = dummy  # 当前节点初始化为虚拟头节点for v in values:current.next = ListNode(v)current = current.nexthead = dummy.next  # 实际头节点为虚拟头节点的下一个节点# 移除元素并打印新链表
sol = Solution()
new_head = sol.removeElements(head, 6)cur = new_head
while cur:print(cur.val)cur = cur.next

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

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

相关文章

【linux】基本指令(中篇)

echo指令 将引号内容打印到显示屏上 输出的重定向 追加的重定向 输出的重定向 我们学习c语言的时候当以写的方式创建一个文件&#xff0c;就会覆盖掉该文件之前的内容 当我们以追加的方式打开文件的时候&#xff0c;原文件内容不会被覆盖而是追加 more指令 10.more指令…

VUE限制文件上传大小和上传格式

<el-form-item label"图片&#xff1a;" prop"tempImagePath"><el-uploadclass"upload"accept"image/jpeg":show-file-list"false"list-type"picture-card":headers"{ token: token}":action&…

openEuler 22.03 LTS x86_64 cephadm 部署ceph 16.2.14 未完成 笔记

环境 准备三台虚拟机 10.47.76.94 node-1 10.47.76.95 node-2 10.47.76.96 node-3 下载cephadm [rootnode-1 ~]# yum install cephadm Last metadata expiration check: 0:11:31 ago on Tue 21 Nov 2023 10:00:20 AM CST. Dependencies resolved. Package …

3.1 CPU内部结构与时钟与指令

CPU内部结构 总线一些自定义部件总线图内存指令执行流程:取指令,译码,执行pc做的事内存地址寄存器内存缓存寄存器指令寄存器,译码第一步指令寄存器传递地址到内存地址寄存器指令MOV_A的过程(译码第二步)第一条指令执行完毕第三条指令的执行第四条指令第四条指令不同的执行流程…

Another app is currently holding the yum lock; waiting for it to exit...

今天使用yum进行下载的时候报错 解决办法&#xff1a; 执行 rm -f /var/run/yum.pid 然后重新运行yum指令即可&#xff0c;发现已经可以正常下载啦&#xff01;

2023年【安全员-C证】考试试卷及安全员-C证试题及解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全员-C证考试试卷是安全生产模拟考试一点通生成的&#xff0c;安全员-C证证模拟考试题库是根据安全员-C证最新版教材汇编出安全员-C证仿真模拟考试。2023年【安全员-C证】考试试卷及安全员-C证试题及解析 1、【多选…

带你用uniapp从零开发一个仿小米商场_4.uniapp中引入阿里图标库中字体图标

字体图标库介绍 CSS中的字体图标是一种使用字体文件来呈现图标的技巧。与传统的图像图标相比&#xff0c;字体图标具有更多的优点&#xff0c;例如易于定制、可扩展性和跨平台兼容性。在CSS中&#xff0c;字体图标通常通过使用字体文件和CSS的font-face规则来引入&#xff0c;…

【差旅游记】走进新疆哈密博物馆

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 前些天在新疆哈密时&#xff0c;有天下午有点时间&#xff0c;看离住的宾馆不远就是哈密博物馆&#xff0c;便去逛了逛博物馆&#xff0c;由于接下来的一段时间没顾上记录&#xff0c;趁今天有些时间简单记录下那短暂的…

ElasticSearch01

ElasticSearch 版本&#xff1a;7.8 学习视频&#xff1a;尚硅谷 笔记&#xff1a;https://zgtsky.top/ ElasticSearch介绍 Elaticsearch&#xff0c;简称为es&#xff0c; es是一个开源的高扩展的分布式全文检索引擎&#xff0c;它可以近乎实时的存储、检索数据&#xff1b…

基于springboot网上超市管理系统

基于springboot网上超市管理系统 摘要 随着互联网的快速发展&#xff0c;电子商务行业迎来了蓬勃的发展&#xff0c;网上超市作为电子商务的一种形式&#xff0c;为消费者提供了便利的购物体验。本文基于Spring Boot框架&#xff0c;设计和实现了一个网上超市管理系统&#xff…

MySQL的基础知识

目录 关系型数据库 SQL通用语法 数据类型 数值类型 字符串类型 日期类型 SQL分类 DDL 数据库操作 表操作 DML 添加数据 修改数据 删除数据 DQL 基本查询 条件查询 聚合函数 分组查询 排序查询 分页查询 执行顺序 DCL 管理用户 权限控制 函数 字符串…

基于51单片机的公交自动报站系统

**单片机设计介绍&#xff0c; 基于51单片机的公交自动报站系统 文章目录 一 概要公交自动报站系统概述工作原理应用与优势 二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 很高兴为您介绍基于51单片机的公交自动报站系统&#xff1a; 公交自动报…