代码随想录(day3)——链表

news2025/1/10 10:11:37

Leetcode.203 移除链表元素:

203. 移除链表元素 - 力扣(LeetCode)

       对于本题,难点就在于对于头部结点的删除,以及给定链表为空时,如何进行遍历。因为需要遍历链表,假设访问链表下一个结点所对应的代码为head->next,若此时的链表为空,则一旦运行该代码,则直接会被判定越界。造成错误。因此,为了解决上述问题,可以在给定的链表的头结点之前,人工添加一个哨兵位头结点。该链表中的val=0,没有任何实际意义。为了方便表述,文章后面针对哨兵位头结点统一命名为phead。具体结构如下:

在测试用例中,可以看到,题目给了这样的数据:

如果用上面的图形来表示这种链式结构,即:

      对于这种连续的头部删除结点,在设置了哨兵位头结点的情况下,只需要检测当前头结点head中的值是否为需要删除的值,即:head->val == val。一旦满足条件,则直接改变head的位置,即head=head->next。不过需要注意,如果此时给定的链表为空,即:

此时head==nullptr,如果不检查,在检查结点的值这一条件是否满足删除所对应的条件时,由于head->val这句代码的运行顺序是先对head解引用,在访问值,此时会对nullptr解引用,造成错误。因此,应该先检测此时的head是否为nullptr

       在进了了上面的删除后,此时链表中,所有需要删除的头结点都已经被删除。但是,还需要再对链表进行一次遍历,检查链表中间结点是否存在需要删除的结点,例如:

       按照题目的要求,需要删除值为6的结点。前面说到,在测试用例中,存在空链表。因此,为了避免造成越界,设置了哨兵位头结点phead。在此处,考虑到遍历链表的过程中,需要不断访问不同的结点,因此,再设置一个专门用于遍历链表的结点cur = phead

      在进行删除时,首先检测cur->next是否为nullptr,如果为空,则说明整个链表遍历完成。如果不为空,则检测cur->next->val == val,如果条件满足,则说明cur指向的下一个结点需要删除,因此令cur->next = cur->next->next。对于此处,可能会有读者担心会不会造成越界。为了方便说明,此处给出一个临界情况:

      对于上述给出的图片,首先进行第一层检测,即:cur->next,由于此时并不为nullptr,并且cur指向的下一个结点中的值为6,因此需要对这个结点进行删除。删除时,需要获取cur->next->next,也就是值为6的结点的下一个结点。也就是nullptr,需要注意,此时并不构成越界。因为在链表的定义中,最后一个结点通常都会让其的next指向nullptr

    上面只给出了cur->next->val == val的情况,如果cur指向的下一个结点中的值不等于需要删除的值,则直接跳过该结点即可。

   在遍历结束后,需要删除掉前面人为创建的哨兵位头结点。返回head。代码如下:

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* phead = new ListNode(0);
        phead->next = head;
       //针对头删的情况
        while( head != nullptr && head->val == val)
        {
            phead->next = head->next;  
            head=head->next;
        }
        ListNode* cur = phead;
        while(cur->next != nullptr)
        {
            if(cur->next->val == val)
            {
                cur->next = cur->next->next;

            }
            else
            {
                cur=cur->next;
            }

        }
        delete phead;
        phead = nullptr;
        return head;

    }
};

   运行结果如下:

Leetcode.707 设计链表:

707. 设计链表 - 力扣(LeetCode)

       对于本题,依旧采用人为添加一个虚拟头结点的方式进行结点。不过需要注意,在题目中并没有给出针对链表中单个结点的结构的定义,因此,需要认为加上上述代码:

struct ListNode
    {
        ListNode(int val)
          :_val(val)
          ,_next(nullptr)
          {}
        int _val;
        ListNode* _next;

    };

在加入后,在给定的类中,将ListNode* phead,int\, \, size作为类的两个成员变量。

随后,在给定类中的构造函数,完成对于虚拟头结点的结构的初始化,即:

 MyLinkedList() {
        _size = 0;
        _phead = nullptr;
    }

其中,size表示链表中结点的数量。

对于头插函数addATHead,只需要先新建一个结点 ,为了方便表示,将这个结点命名为newnode。令newnode->next = phead->next。再phead->next = newnode。具体代码如下:

  void addAtHead(int val) {
        ListNode* newnode = new ListNode(val);
        newnode->_next = _phead->_next;
        _phead->_next = newnode;
        _size++;
    }

其效果可以用下面的图进行表示:

此处需要注意,虚拟头结点并不算一个真正的结点。在题干中说到,链表中结点的下标是从0开始的,也就是说,对于插入的第一个头结点,其下标为0

       对于返回值函数get,需要注意题中传递的参数index是返回下标为index的值。但是,由于链表中第一个结点的下标为0,也就是说,链表中的第三个结点的下标为2。但是size表示的结点的个数,因此为3。所以,在进行index合法性检测时,需要检测index>size-1index<0

      假设在链表中已有4个结点,返回结点的下标为3,即返回链表中最后一个结点。则首先定义一个指针指向第0个结点,然后向后遍历3次即可。对应代码如下:
 

int get(int index) {

        if(index > (_size-1) || index < 0)
        {
            return -1;
        }
        ListNode* cur = _phead->_next;
        while(index--)
        {
            cur = cur->_next;
        }
        return cur->_val;

    }

对于尾插函数addAtTail,原理简单,直接给出代码,不做多余解释

void addAtTail(int val) {
        ListNode* cur = _phead;
        while(cur->_next != nullptr)
        {
            cur = cur->_next;
        }

        ListNode* newnode = new ListNode(val);
        newnode->_next = cur->_next;
        cur->_next = newnode;
        _size++;

    }

       对于插入函数addAtIndex,需要注意,题目要求在index位置之前插入元素。因此,需要找到index-1这个下标所对应的元素。前面说到,由于链表中第一个结点的下标是从0开始的。所以在链表中下标为index的结点,在链表中的位置其实是index+1。例如当index==3时,对应这个下标的结点是链表中的第四个结点。对于找到这个结点,需要从第0个结点开始,向后遍历index次。此时找到的结点是链表中第index+1个结点。

     由于要求招待index位置前一个位置的结点,所以只需要改变遍历起点的位置即可,即改为哨兵位头结点。

     但是需要注意,对于index需要进行合法性检测。题目说到了,当index==size时,视作尾插,因此只需要检测index>size这一种情况即可。

     对应代码如下:
 

void addAtIndex(int index, int val) {

        if(index > _size || index < 0)
        {
            return ;
        }
        
        ListNode* cur = _phead;
       
        while(index--)
        {
            cur = cur->_next;
            
        }

        ListNode* newnode = new ListNode(val);
        newnode->_next = cur->_next;
        cur->_next = newnode;
        _size++;

    }

对于删除结点函数,需要注意,按照删除结点的逻辑,在遍历时,能遍历到的最后一个结点便是链表中倒数第二个结点。因此,如果index==size,此时会遍历到最后一个结点,在后续造成非法访问。因此,检测条件需要进行改变。对应代码如下:

 void deleteAtIndex(int index) {

        if(index >= _size || index < 0)
        {
            return ;
        }

        ListNode* cur = _phead;
        while(index--)
        {
            cur = cur->_next;
        }

        ListNode* tmp = cur->_next;
        cur->_next = cur->_next->_next;
        delete tmp;
        tmp = nullptr;
        _size--;

    }

题目整体代码如下:
 

class MyLinkedList {
public:
    
    struct ListNode
    {
        ListNode(int val)
           : _val(val)
           , _next(nullptr)
           {}

        ListNode* _next;
        int _val;
    };
    MyLinkedList() {
        
         _phead = new ListNode(0);
        _size =0;


    }
    
    int get(int index) {

        if(index > _size-1 || index < 0)
        {
            return -1;
        }
        ListNode* cur = _phead->_next;

        while(index--)
        {
            cur = cur->_next;
        }

        return cur->_val;

    }
    
    void addAtHead(int val) {

        ListNode* newnode = new ListNode(val);
        newnode->_next = _phead->_next;
        _phead->_next = newnode;
        _size++;
    }
    
    void addAtTail(int val) {

        ListNode* cur = _phead;
        while(cur->_next != nullptr)
        {
            cur = cur->_next;
        }

        ListNode* newnode = new ListNode(val);
        newnode->_next = cur->_next;
        cur->_next = newnode;
        _size++;


    }
    
    void addAtIndex(int index, int val) {

        if(index > _size || index < 0)
        {
            return ;
        }
        
        ListNode* cur = _phead;
       
        while(index--)
        {
            cur = cur->_next;
            
        }

        ListNode* newnode = new ListNode(val);
        newnode->_next = cur->_next;
        cur->_next = newnode;
        _size++;

    }
    
    void deleteAtIndex(int index) {

        if(index >= _size || index < 0)
        {
            return ;
        }

        ListNode* cur = _phead;
        while(index--)
        {
            cur = cur->_next;
        }

        ListNode* tmp = cur->_next;
        cur->_next = cur->_next->_next;
        delete tmp;
        tmp = nullptr;
        _size--;

    }

   ListNode* _phead;
   int _size;

};

运行结果如下:

Leetcode.206 反转链表:

206. 反转链表 - 力扣(LeetCode)

依旧采用人为添加哨兵位头结点的方式,原理较为简单,只给出图形表示:

先保存cur的后一个结点tmp,接着改变cur的指向,使其指向pre,对于pre可以看作哨兵位头结点,随后让pre = cur,让cur=tmp即可。一直循环该过程。

对应代码如下:
 

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        
        ListNode* cur = head;
        ListNode* pre = nullptr;
        ListNode* tmp = nullptr;
        while(cur)
        {
            tmp = cur->next;
            cur->next = pre;

            pre = cur;
            cur = tmp;
        }
        return pre;
        

    }
};

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

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

相关文章

开源绘图工具 PlantUML 入门教程(常用于画类图、用例图、时序图等)

文章目录 一、类图二、用例图三、时序图 一、类图 类的UML图示 startuml skinparam classAttributeIconSize 0 class Dummy {-field1 : String#field2 : int~method1() : Stringmethod2() : void } enduml定义能见度&#xff08;可访问性&#xff09; startumlclass Dummy {-f…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的行人跌倒检测系统(深度学习+UI界面+完整训练数据集)

摘要&#xff1a;开发行人跌倒检测系统在确保老年人安全方面扮演着至关重要的角色。本篇文章详尽地阐述了如何利用深度学习技术构建一个行人跌倒检测系统&#xff0c;并附上了完整的代码实现。该系统采用了先进的YOLOv8算法&#xff0c;并对YOLOv7、YOLOv6、YOLOv5等先前版本进…

ARM64汇编05 - MOV系列指令

MOV(wide immediate) MOV 可以将一个立即数移动到寄存器中。 .text:0000000000000834 80 46 82 D2 MOV X0, #0x1234 ; Keypatch modified this from:MOV X0, #0x1234 对应的汇编代码为&#xff1a;80 46 82 D2 看手册可知&#xf…

多维时序 | Matlab实现VMD-CNN-BiLSTM变分模态分解结合卷积神经网络结合双向长短期记忆神经网络多变量时间序列预测

多维时序 | Matlab实现VMD-CNN-BiLSTM变分模态分解结合卷积神经网络结合双向长短期记忆神经网络多变量时间序列预测 目录 多维时序 | Matlab实现VMD-CNN-BiLSTM变分模态分解结合卷积神经网络结合双向长短期记忆神经网络多变量时间序列预测预测效果基本介绍程序设计参考资料 预测…

利用“定时执行专家”软件的25种任务与12种触发器,提升IT系统管理自动化水平

在IT系统管理中&#xff0c;自动化是提高工作效率、减少人为错误的关键。而《定时执行专家》这款软件&#xff0c;以其强大的功能、易用性和毫秒级的执行精度&#xff0c;成为了IT系统管理员的得力助手。今天&#xff0c;我们就来探讨一下如何利用这款软件的25种任务类型和12种…

如何在Linux系统安装SVN并配置固定公网地址远程访问【内网穿透】

文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…

2024-03-11,12(HTML,CSS)

1.HTML的作用就是在浏览器摆放内容。 2.HTML基本骨架 head&#xff1a;网页头部&#xff0c;是给浏览器看的代码&#xff0c;例如CSS body&#xff1a;网页主体&#xff0c;是给用户看的代码&#xff0c;例如图片&#xff0c;文字。 title&#xff1a;网页标题 3.标签的两种…

Redis中set,zset

集合类型set中的数据是无序的&#xff0c;不能重复的 SET SADD key value [value....] 将一个或者多个元素添加到集合set中&#xff0c;重复的元素是无法进行添加的 返回值为添加成功的数字smembers key 获取set中所有的元素&#xff0c;返回元素的顺序是无序的sismember key…

React Hooks 那些事儿

翻了波之前写的文章还有笔记&#xff0c;发现关于前端的文章并不多&#xff08;好歹也划水做过点前端开发&#xff09;。巧了&#xff0c;最近没什么好话题可写&#xff0c;做下 React Hooks 学习笔记吧。 Effect Hook 不得不说 Hook 的出现降低了我们在 React 中处理副作用&…

【漏洞复现】SpringBlade error/list SQL 注入漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

定时执行专家 —— 让工作更高效,生活更便捷

在现代社会&#xff0c;高效的时间管理已经成为我们工作和生活中不可或缺的一部分。为了实现这一目标&#xff0c;我们经常会借助各种工具和软件来辅助我们完成定时任务。今天&#xff0c;我要为大家介绍一款功能强大、操作简便的定时任务执行软件——《定时执行专家》。这款软…

上海计算机学会 2023年11月月赛 丙组T5 推箱子(数学 思维 排序)

第五题&#xff1a;T5推箱子 标签&#xff1a;排序、数学、思维题意&#xff1a;给定 t t t组数据&#xff0c;每组数据给定长度为 n n n的字符串&#xff0c; 表示箱子&#xff0c; _ \_ _表示空格&#xff0c;求把箱子都推到一起&#xff08;即两两箱子之间没有空格&#…

idea+maven+tomcat+spring 创建一个jsp项目

概述&#xff1a;我真服了&#xff0c;这个垃圾学校还在教jsp&#xff0c;这种技术我虽然早会了&#xff0c;但是之前搞的大多都是springboot web类型的&#xff0c;这里我就复习一下&#xff0c;避免以后忘记这种垃圾技术 第一步&#xff1a;创建maven项目 第二步&#xff1a…

Leetcode 3.12

leetcode hot 100 链表1.两两交换链表中的节点2.随机链表的复制3.排序链表 链表 1.两两交换链表中的节点 两两交换链表中的节点 1.必须要设置一个dummy (temp) 结点2.保存第二个节点3.先让第一个节点指向第三个节点4.再让第二个节点指向第一个节点5.最后让dummy指向第二个节点…

基于深度学习的番茄叶片病害检测系统(含UI界面、yolov8、Python代码、数据集)

项目介绍 项目中所用到的算法模型和数据集等信息如下&#xff1a; 算法模型&#xff1a;     yolov8 yolov8主要包含以下几种创新&#xff1a;         1. 可以任意更换主干结构&#xff0c;支持几百种网络主干。 数据集&#xff1a;     网上下载的数据集&#x…

宏景eHR downlawbase SQL注入漏洞复现

0x01 产品简介 宏景eHR人力资源管理软件是一款人力资源管理与数字化应用相融合,满足动态化、协同化、流程化、战略化需求的软件。面向复杂单组织或多组织客户,支持流程,B/S架构。特别适合集团化管理和跨地域使用的产品,融合了最新的互联网技术和先进的人力资源管理理念和实…

浏览器与服务器通信过程(HTTP协议)

目录 1 概念 2 常见的 web 服务器有 3 浏览器与服务器通信过程 3.1 DNS 3.2 URL 4 HTTP请求方法和应答状态码 4.1 HTTP请求报文段实例 4.2 HTTP请求方法 5 HTTP应答报头和应答状态 5.1 HTTP的应答报头结构 5.2 HTTP的应答状态 1 概念 浏览器与 web 服务器在应用层通…

【DAY11 软考中级备考笔记】数据结构 查找和排序

数据结构 查找和排序 3月12日 – 天气&#xff1a;晴 1. 顺序查找 顺序查找就是简单的从头一个一个的进行比较&#xff0c;注意它的平均查找长度 2. 折半查找 折半查找和二叉排序树一致&#xff1a; 优点&#xff1a;查找效率很高 缺点&#xff1a;要求必须是循序存储并且表中…

UVC 设备框架在 Linux 4.15 内核的演变

1. 概述 发现之前的uvc框架和现在的还是有一些差别的&#xff08;比如从videobuf 过渡到videobuf2&#xff09;&#xff0c;写个blog记录一下&#xff0c;方便以后查询&#xff0c;我的内核版本&#xff1a;Linux 4.15 UVC&#xff08;USB Video Class&#xff09;设备框架是…

Shadertoy内置函数系列 - mod 取模运算

mod函数返回x % 3的结果 先看一个挑战问题题目&#xff1a; Create a pattern of alternating black and red columns, with 9 columns of each color. Then, hide every third column that is colored red.The shader should avoid using branching or conditional statemen…