【链表】leetcode203.移除链表元素(C/C++/Java/Js)

news2024/11/24 17:32:04

leetcode203.移除链表元素

  • 1 题目
  • 2 思路 (两种方式)
    • 2.1 在原来链表上进行删除
    • 2.2 设置一个虚拟头结点删除
  • 3 代码
    • 3.1 C++ (两种方式)
    • 3.2 C版本(两种方式)
    • 3.3 Java版本(两种方式)
    • 3.4 JavaScript版本
  • 4 总结


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++编程语言的话,不要忘了还要从内存中删除这两个移除的节点, 清理节点内存之后如图:
C:free( p);
C++: delete p;

在这里插入图片描述
当然如果使用java ,python的话就不用手动管理内存了。

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

这种情况下的移除操作,就是让节点next指针直接指向下下一个节点就可以了,

那么因为单链表的特殊性,只能指向下一个节点,刚刚删除的是链表的中第二个,和第四个节点,那么如果删除的是头结点又该怎么办呢?
这里就涉及如下链表操作的两种方式:


2.1 在原来链表上进行删除

在这里插入图片描述
移除头结点和移除其他节点的操作是不一样的,因为链表的其他节点都是通过前一个节点来移除当前节点,而头结点没有前一个节点。

所以头结点如何移除呢,其实只要将头结点向后移动一位就可以,这样就从链表中移除了一个头结点。
在这里插入图片描述
依然别忘将原头结点从内存中删掉。
在这里插入图片描述
这样移除了一个头结点,是不是发现,在单链表中移除头结点 和 移除其他节点的操作方式是不一样,其实在写代码的时候也会发现,需要单独写一段逻辑来处理移除头结点的情况。

那么可不可以 以一种统一的逻辑来移除 链表的节点呢。
其实可以设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除了。


2.2 设置一个虚拟头结点删除

来看看如何设置一个虚拟头。依然还是在这个链表中,移除元素1。
在这里插入图片描述
这里来给链表添加一个虚拟头结点为新的头结点,此时要移除这个旧头结点元素1。

这样是不是就可以使用和移除链表其他节点的方式统一了呢?

来看一下,如何移除元素1 呢,还是熟悉的方式,然后从内存中删除元素1。

最后呢在题目中,return 头结点的时候,别忘了 return dummyNode->next;, 这才是新的头结点。


3 代码

3.1 C++ (两种方式)

直接使用原来的链表来进行移除节点操作:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        // 删除头结点
        while (head != NULL && head->val == val) { // 注意这里不是if
            ListNode* tmp = head;
            head = head->next;
            delete tmp;
        }

        // 删除非头结点
        ListNode* cur = head;
        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;
    }
};

设置一个虚拟头结点在进行移除节点操作:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
 class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
        dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
        ListNode* pre = dummyHead, *cur = dummyHead->next;
        while (cur != NULL) {
            if(cur->val == val) {
                ListNode* tmp = cur;
                cur = cur->next;
                pre->next = cur;
                delete tmp;
            } else {
                pre = cur;
                cur = cur->next;
            }
        }
        head = dummyHead->next;
        delete dummyHead;
        return head;
    }
};
 

3.2 C版本(两种方式)

C: 用原来的链表操作:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode *temp = NULL;
    while (head && head->val == val) {//处理链表头部就是待删元素的情况
        temp = head;
        head = head->next;
        free(temp);
    }
    if (!head) return head;//如果链表为空直接返回
    struct ListNode *pre = head, *cur = head->next;//pre指向前一个结点,cur指向当前结点
    //这种情况head位置一定不是待删元素,因为上面已经处理完了
    while (cur) {
        if (cur && cur->val == val) { //如果cur位置是待删元素
            temp = cur;
            cur = cur->next;
            pre ->next = cur;
            free(temp);
        }
        else {//cur位置不是待删元素,继续向后遍历
            pre = cur;
            cur = cur->next;
        }
    }
    return head;
}

设置一个虚拟头结点:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */


struct ListNode* removeElements(struct ListNode* head, int val){
    typedef struct ListNode ListNode;
    ListNode *shead;
    shead = (ListNode *)malloc(sizeof(ListNode));
    shead->next = head;
    ListNode *cur = shead;
    while(cur->next != NULL){
        if (cur->next->val == val){
            ListNode *tmp = cur->next;
            cur->next = cur->next->next;
            free(tmp);
        }
        else{
            cur = cur->next;
        }
    }
    head = shead->next;
    free(shead);
    return head;
}

3.3 Java版本(两种方式)

/**
 * 不添加虚拟节点and pre Node方式
 * 时间复杂度 O(n)
 * 空间复杂度 O(1)
 * @param head
 * @param val
 * @return
 */
public ListNode removeElements(ListNode head, int val) {
    while(head!=null && head.val==val){
        head = head.next;
    }
    ListNode curr = head;
    while(curr!=null){
        while(curr.next!=null && curr.next.val == val){
            curr.next = curr.next.next;
        }
        curr = curr.next;
    }
    return head;
}
/**
 * 添加虚节点方式
 * 时间复杂度 O(n)
 * 空间复杂度 O(1)
 * @param head
 * @param val
 * @return
 */
public ListNode removeElements(ListNode head, int val) {
    if (head == null) {
        return head;
    }
    // 因为删除可能涉及到头节点,所以设置dummy节点,统一操作
    ListNode dummy = new ListNode(-1, head);
    ListNode pre = dummy;
    ListNode cur = head;
    while (cur != null) {
        if (cur.val == val) {
            pre.next = cur.next;
        } else {
            pre = cur;
        }
        cur = cur.next;
    }
    return dummy.next;
}

3.4 JavaScript版本

/**
 * @param {ListNode} head
 * @param {number} val
 * @return {ListNode}
 */
var removeElements = function(head, val) {
    const ret = new ListNode(0, head);
    let cur = ret;
    while(cur.next) {
        if(cur.next.val === val) {
            cur.next =  cur.next.next;
            continue;
        }
        cur = cur.next;
    }
    return ret.next;
};

4 总结

真正理解到单链表的结构和删除操作后,本题是非常基础和简单的。
主要掌握两种方式:

  • 直接使用原来的链表来进行删除操作。
  • 设置一个虚拟头结点在进行删除操作。

在笔试中有的题可能会告诉你链表包含一个头结点,头结点不存放数据,这个时候也是方式二的处理思路。
而本题,没有头结点,我们就创造头结点。正所谓没有路我们就创造路。


内容整理于Carl老师的《代码随想录》,强推!

代码随想录

By – Suki 2023/1/6
没有路,我们就创造路。

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

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

相关文章

Vue的组件、组件的创建、data、methods

一、组件 组件是vue的重要的特征之一&#xff0c;可以扩展html的功能&#xff0c;也可以封装代码实现重复使用。 二、组件的创建 1. 非脚手架方式下创建 ​ 第一步&#xff1a;使用Vue.extend创建组件 ​ 第二步&#xff1a;使用Vue.component注册组件 ​ …

OpenGov(三):新波卡治理机制有哪些可期待?

OpenGov维持波卡开创的信念投票&#xff0c;与以前相同的方式进行&#xff0c;使用WebAssembly和几个链上投票机制。也就是说&#xff0c;OpenGov通过降低障碍&#xff0c;来更好地管理网络的日常决策&#xff0c;将流程推向去中心化。真正的重点是使提案的范围与通过治理流程的…

企业数字化转型到底是什么?

企业的数字化转型单单是从基础设施上变更&#xff0c;更要从企业数据从文化上入手&#xff0c;培养企业的数据文化&#xff0c;以数据驱动来促进业务发展。大家都把数据基础设施讲的很详细了&#xff0c;那么我就从企业的数据化转型当中的数据文化是什么&#xff1f;以下来为大…

Python类型注解(十)

python学习之旅(十) &#x1f44d;查看更多可以关注查看首页或点击下方专栏目录 一.为什么需要类型注解 在代码中提供数据类型的注解&#xff08;显式的说明&#xff09;&#xff0c;使用时能获得相关提示 帮助第三方IDE工具&#xff08;如PyCharm&#xff09;对代码进行类型推…

想从事网络信息安全的工作,该如何自学?

前言 【一一帮助网络安全入门和提升学习点这里一一】 由于我之前写了不少网络安全技术相关的文章&#xff0c;不少读者朋友知道我是从事网络安全相关的工作&#xff0c;于是经常有人私信问我&#xff1a; 我刚入门网络安全&#xff0c;该怎么学&#xff1f;要学哪些东西&#…

第56篇-利用jsRpc获取某博的登录参数

声明:该专栏涉及的所有案例均为学习使用,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关!如有侵权,请私信联系本人删帖! 文章目录 一、前言二、JsRpc的基本使用1.准备工作2.简单使用三、使用jsRpc获取微博登录参数1.网站分析2.构建rpc一、前言 以前使用…

记录 一次 小米路由器4C 刷openwrt 过程

前言 起因是4C的性能不太行&#xff0c;用久了网络也不稳定&#xff0c;且100M带宽跑不满&#xff0c;然后就换了路由器&#xff0c;闲置的这个准备哪来跑个Linux挂个bot来着&#xff0c;结果可好&#xff0c;刷完发现内存小的可怜呀&#xff0c;架构也不是主流的&#xff08;…

低代码助力工业软件发展,提升智能制造“软”实力

在《“十四五”智能制造发展规划》中&#xff0c;将工业软件作为加强自主供给的一个重点任务进行单独部署&#xff0c;强调了工业软件的工业属性&#xff0c;明确了工业软件对于智能制造的核心支撑作用&#xff0c;凸显了我国补足工业软件短板、以工业软件助推智能制造发展的决…

跨境资讯 | 亚马逊三站点将更新供应链标准,1月19日生效

让我们一起来看看今日都有哪些新鲜事吧&#xff01;01 亚马逊将更新供应链标准 亚马逊美国站、欧洲站和日本站发布公告称2023年1月19日将更新供应链标准&#xff0c;在亚马逊销售的产品必须符合这些新标准。作为定期审查的一部分&#xff0c;这些标准每三年更新一次。亚马逊表…

虹科案例 | 解决ASRS系统的痛点问题居然这么简单?(下)

ASRS中的定位器 在考虑传感技术时&#xff0c;重要的是每种技术都能够以最高程度的重复性和精确度保持绝对分量&#xff0c;并非所有的方法都是一样托盘梭子和立式起重机在任何时候都要求绝对位置。 托盘梭子&#xff1a; 过道位置 行位置 垂直起重机&#xff1a; 高度 线性…

Java中解决lambda表达式内部访问在其外部定义的变量-使用mapToInt

场景 Java8新特性-Stream对集合进行操作的常用API&#xff1a; Java8新特性-Stream对集合进行操作的常用API_霸道流氓气质的博客-CSDN博客_streamapi对集合修改 上面介绍Stream的相关使用示例。 如果遇到在lambda表达式内部访问在其外部定义的变量&#xff0c;比如一个求和…

MATLAB-surf/ezsurf函数绘制三维图形

&#xff08;1&#xff09;surf 函数的用法和 mesh函数类似&#xff0c;MATLAB中 surf函数专门用于绘制三维着色曲面图和 surfc是通过矩形区域来观测数学函数的函数。surf和 surfc能够产生由X、Y、Z指定的有色参数化曲面&#xff0c;即三维有色图。具体调用方法如下。1、surf(Z…

JDBC数据库连接

下载jdbc jar包&#xff0c;中央仓库下载https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.24项目导入右键jar包&#xff0c;然后add as library数据库操作3.1连接数据库package com.heima.jdbc;import java.sql.Connection; import java.sql.DriverManager…

Appium自动化测试环境搭建

Appium自动化环境搭建 首先整体了解一下Appium自动化环境搭建都需要哪些软件或者组件 Python、Appium、AndroidSDK&#xff08;主要是adb.exe、aapt.exe&#xff09;、Node Js、java 一、安装并配置java环境 1、这个可以搜到的教程实在是太多了&#xff0c;建议直接官方下载…

汽车数据分析,2022年汽车产量总体高于2021年,年产量增长了6%左右

哈喽&#xff0c;大家好&#xff0c;春节将近&#xff0c;想必大家也开始抢票准备回家过年了&#xff0c;有车的伙伴也可能打算自驾归家了。大家辛苦工作了一年&#xff0c;手里积攒了一些积蓄&#xff0c;有些伙伴可能想赶在春节购车购房&#xff0c;这里小编为大家准备了一些…

java面试之设计篇

一、基础 1.六大设计原则 单一职责原则 一个类只专注于做一件事&#xff1b;高内聚&#xff0c;低耦合&#xff1b; 开闭原则 对拓展开放&#xff0c;对修改关闭&#xff08;尽可能不动原有代码进行拓展&#xff09;&#xff1b; 高内聚&#xff0c;低耦合&#xff1b; 为达到…

电力系统|基于分布式高斯-牛顿方法结合置信传播 (BP) 的概率推理方法的非线性状态估计 (SE) 模型(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f4dd;目前更新&#xff1a;&#x1f31f;&#x1f31f;&#x1f31f;电力系统相关知识&#xff0c;期刊论文&…

新考纲下的PMP考试有多难?

一&#xff0c;2022新考纲PMP考试有多难&#xff1f; PMP考试被认为是最难的项目管理考试之一&#xff0c;主要是因为其庞大的教学大纲、所需的投入的精力、所问问题的类型和长度、考试时间和答案选择。它测试候选人对项目管理技能和耐心水平的深入了解。这并不意味着不可能通…

舆情监测是什么技术,网络舆情监测技术操作规范?

网络舆情监测是对互联网上公众的言论和观点进行监视和预测的行为&#xff0c;随着互联网的发展&#xff0c;舆情监测已经是企业日常重要工作&#xff0c;对于企业来说是非常重要的&#xff0c;接下来TOOM舆情监测带您了解舆情监测是什么技术&#xff0c;网络舆情监测技术操作规…

基于Python卷积神经网络的动物识别系统源码,动物检测系统源码,宠物识别系统源码

毕设系列-基于卷积神经网络的动物识别系统 完整代码下载地址&#xff1a;基于Python卷积神经网络的动物识别系统源码 上期评论区有好兄弟留言想看动物检测系统&#xff0c;那咱们这期检测系列就更新动物检测系统&#xff0c;并且在之前功能的基础之上添加了计数的功能&#x…