首页 > 编程语言 >203. 移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

203. 移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

时间:2024-08-06 21:28:44浏览次数:18  
标签:current ListNode val next 链表 节点

在链表中,每个节点都有一个指向下一个节点的指针。删除一个节点的本质是将前一个节点的指针指向要删除节点的下一个节点,从而跳过要删除的节点。以下是详细解释为什么以及如何这样做:

1. **链表的结构**:
   一个链表节点包含两个部分:存储的数据和指向下一个节点的指针。
   ```cpp
   struct ListNode {
       int val;
       ListNode* next;
       ListNode(int x) : val(x), next(nullptr) {}
   };
   ```

2. **删除节点的操作**:
   为了从链表中删除一个节点,我们需要调整前一个节点的指针,使其指向要删除节点的下一个节点。

   假设我们有一个链表:`1 -> 2 -> 6 -> 3 -> 4 -> 5 -> 6`,我们要删除所有值为 `6` 的节点。删除节点 `6` 时,我们需要让前一个节点(例如 `2`)的 `next` 指向节点 `6` 的下一个节点(即 `3`)。

3. **指针操作的具体步骤**:
   - 我们遍历链表,用指针 `current` 指向当前节点,用指针 `prev` 指向当前节点的前一个节点。
   - 如果 `current->val` 等于 `val`,即我们要删除的节点,我们需要跳过这个节点。
   - `prev->next = current->next` 这行代码的作用是:将前一个节点的 `next` 指针指向当前节点的下一个节点。这样,当前节点 `current` 就被跳过了,相当于从链表中删除了。

4. **为什么这样写**:
   通过这种方式,我们可以有效地删除节点,而不需要实际释放节点的内存。这种方式也避免了重新遍历链表或创建新的链表。

   ```cpp
   class Solution {
   public:
       ListNode* removeElements(ListNode* head, int val) {
           ListNode* dummyHead = new ListNode(0); // 创建虚拟头节点
           dummyHead->next = head;
           ListNode* current = head;
           ListNode* prev = dummyHead;
           
           while (current != nullptr) {
               if (current->val == val) { // 如果当前节点的值等于给定值
                   prev->next = current->next; // 跳过当前节点
               } else {
                   prev = current; // 前一个节点移动到当前节点
               }
               current = current->next; // 当前节点移动到下一个节点
           }
           
           ListNode* newHead = dummyHead->next;
           delete dummyHead; // 释放虚拟头节点的内存
           return newHead;
       }
   };
   写法1:class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        // 设置一个虚拟头节点
        // 这个虚拟头节点有助于处理删除头节点的情况
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        
        // 初始化当前节点和前一个节点指针
        // current指向实际的头节点,prev指向虚拟头节点
        ListNode* current = head;
        ListNode* prev = dummyHead;
        
        // 遍历链表
        while (current != nullptr) {
            // 如果当前节点的值等于给定值val
            if (current->val == val) {
                // 跳过当前节点,即将前一个节点的next指针指向当前节点的下一个节点
                prev->next = current->next;
            } else {
                // 如果当前节点的值不等于val,则前一个节点移动到当前节点
                prev = current;
            }
            // 当前节点向前移动
            current = current->next;
        }
        
        // 新的头节点是虚拟头节点的下一个节点
        ListNode* newHead = dummyHead->next;
        // 释放虚拟头节点的内存
        delete dummyHead;
        return newHead;
    }
};
写法2:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        // 设置一个虚拟头结点,以处理删除头节点的情况
        ListNode* dummyHead = new ListNode(0);
        // 将虚拟头结点指向head,这样方便后面做删除操作
        dummyHead->next = head;
        // 初始化当前节点指针,指向虚拟头节点
        ListNode* cur = dummyHead;
        
        // 遍历链表,直到最后一个节点
        while (cur->next != NULL) {
            // 如果下一个节点的值等于给定值val
            if (cur->next->val == val) {
                // 保存需要删除的节点
                ListNode* tmp = cur->next;
                // 将当前节点的next指向需要删除节点的下一个节点,跳过需要删除的节点
                cur->next = cur->next->next;
                // 释放被删除节点的内存
                delete tmp;
            } else {
                // 如果下一个节点的值不等于val,当前节点指针向前移动
                cur = cur->next;
            }
        }
        
        // 更新head指针,指向新的头节点
        head = dummyHead->next;
        // 释放虚拟头结点的内存
        delete dummyHead;
        // 返回新的头节点
        return head;
    }
};

通过使用虚拟头节点 (dummyHead) 和当前节点 (cur) 来维护和操作链表,使得代码在处理删除节点时更加简洁和统一。这里的关键点是通过 cur 指针的移动和判断,来确保正确地删除节点并维护链表的完整性。

标签:current,ListNode,val,next,链表,节点
From: https://blog.csdn.net/qq_46243318/article/details/140965960

相关文章

  • SQLServer 事务复制订阅节点非活跃状态(inactive)错误的处理:Error in replication::subs
    事务复制中订阅节点非活动( inactive)错误在SQLServer的事务复制模型中,会出现“订阅过期”的错误,相关订阅分发代理Job的典型错误如下:"AgentSQLNYC01-Onvoices-PubInvoicesInvoices-SQLNYC01-1353is retryingafteranerror. 211retriesattempted.Seeagentjobhistoryin......
  • Element el-form 表单校验,保存或提交验证某一项或者多项;validateField 的使用
    通常新增或者编辑对form表单的校验都是全局性的校验:this.$refs.form.validate(valid=>{if(valid){//校验通过,业务逻辑代码...}});如果需要对表单里的特定几个必填项进行校验,应该如何实现? 业务场景:下图点击保存按钮时,只需要校验前两项,其余参数不......
  • 数据结构——链表
    数据结构——链表概念代码实现节点申请节点空间尾插头插尾删头删查找在指定位置之前插入数据在指定位置之后插入数据删除pos节点删除pos后一节点销毁链表概念链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的......
  • etcd单节点部署
    环境:OS:Centos7etcd:etcd-v3.5.15 1.下载地址https://github.com/etcd-io/etcd/releases/tag/v3.5.15直接下载编译好的二进制文件包,下载文件如下:etcd-v3.5.15-linux-amd64.tar.gz2.解压安装[root@host135milvus]#tar-xvfetcd-v3.5.15-linux-amd64.tar.gz[root@host135......
  • 数据结构----链表
        接下来我打算更新数据结构相关方面的知识,使用的语言是Java,但是其中的逻辑和思路并不影响。如果感兴趣可以关注合集。    希望大家看完之后可以自己去手敲实现一遍,同时在最后我也列出一些基本和经典的题目,可以尝试做一下。大家也可以自己去力扣或者洛谷牛客......
  • 【链表OJ】常见面试题 2
    文章目录1.[链表分割](https://www.nowcoder.com/practice/0e27e0b064de4eacac178676ef9c9d70?tpId=8&&tqId=11004&rp=2&ru=/activity/oj&qru=/ta/cracking-the-coding-interview/question-ranking)1.1题目要求1.2哨兵位法2.[链表的回文结构](https://www.nowcoder.co......
  • ComfyUI插件:efficiency-nodes-comfyui节点
    前言:学习ComfyUI是一场持久战,efficiency-nodes-comfyui是提高工作流创造效率的工具,包含效率节点整合工作流中的基础功能,比如EfficientLoader节点相当于LoadCheckpoint+Clipsetlayer+LoadVAE等等的合集,并且该插件提供了更加简便快捷的X/Y对比图,能够使测评工作的效率进一步提......
  • 【数据结构】反转链表,合并有序链表,有无环的判断
    前言:小编在上期进行了单链表的模拟,这期接上期进行单链表相关题目讲解1.反转单链表 1.1.题目题目来源:.-力扣(LeetCode)给定一个单链表,实现单链表的反转,图示如下:1.2.解题思路首先在反转时,应该用到头插法,即将第一个后面的元素逐步插入到头结点之前,这里头结点每次要进......
  • javax.validation包校验嵌套属性(List对象)的写法
    1maven依赖<!--HibernateValidator用于数据验证--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId></depende......
  • 【数据结构】单链表
    前言:小编这里将讨论无头单向非循环的单链表。1.ArrayList的缺陷 在上一期中,小编模拟了列表的相关操作实现,可以发现在增删的过程中非常麻烦,每次增加,或者删除数据的时候,都需要将操作下标的后面所有数据进行前移或者后移。上期博客:http://t.csdnimg.cn/VI2yz所以:由于其......