代码随想录算法训练营15期 Day 3 | 203.移除链表元素 、707.设计链表 、206.反转链表

news2024/10/7 14:23:44

今日任务 

  •  链表理论基础 
  •  203.移除链表元素 
  •  707.设计链表 
  •  206.反转链表 

链表理论基础 

链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

单链表

 双链表

循环链表---可以用来解决约瑟夫环的问题 

数组是在内存中是连续分布的,但是链表在内存中可不是连续分布的。

链表是通过指针域的指针链接在内存中各个节点。

所以链表中的节点在内存中不是连续分布的 ,而是散乱分布在内存中的某地址上,分配机制取决于操作系统的内存管理。

链表起始节点为2, 终止节点为7, 各个节点分布在内存的不同地址空间上,通过指针串联在一起。

链表的构造函数

// 单链表
struct ListNode {
    int val;  // 节点上存储的元素
    ListNode *next;  // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
};

但是上面的这个写法有点怪异,可以使用下面的这个写法

struct ListNode
{
    double value;
    ListNode *next;
    //构造函数
    ListNode(double valuel, ListNode *nextl = nullptr)
    {
        value = value1;
        next = next1;
    }
};

注意点:nullptr与NULL的区别?

①在c++98和c++03之中,NULL默认情况下被定义为无符号整型常量0,否则为无类型指针常量 (void*) 0。

#ifndef NULL
    #ifdef __cplusplus
        #define NULL 0
    #else
        #define NULL ((void *)0)
    #endif
#endif

继而下面两句的运行结果是相同的.

void test(int)
{
	cout << "test(int)" << endl;
}


int main()
{
	test(0);
	test(NULL);
	
	return 0;
}

这是因为在 C++中,字面常量 0 既可以表示一个整形常量 0,也可以表示无类型指针常量 (void*) 0,但是编译器默认把它看成是一个整形常量 0 (如果把 0 当指针使用,就必须对其进行强转 (void*) 0 )。
由于 NULL 被定义为 0,编译器默认 NULL 就是整形常量 0,所以 test(NULL) 调用 test(int) 函数,而非 test(int*) 函数。
②在c++11出来之后,C++11标准增加了新的关键字 nullptr,保证在任何情况下都表示空指针。

void test(int)
{
	cout << "test(int)" << endl;
}

void test(int*)
{
	cout << "test(int*)" << endl;
}

int main()
{
	test(0);
	test(NULL);
	test(nullptr);
	return 0;
}

链表操作---删除节点

注意此时,D任然在内存之中,需要手动释放掉才可以。

链表操作---添加节点

链表的增添和删除都是O(1)操作,也不会影响到其他节点。要是删除第五个节点,需要从头节点查找到第四个节点通过next指针进行删除操作,查找的时间复杂度是O(n)。

性能分析

数组在定义的时候,长度就是固定的,如果想改动数组的长度,就需要重新定义一个新的数组。
链表的长度可以是不固定的,并且可以动态增删, 适合数据量不固定,频繁增删,较少查询的场景。

203.移除链表元素

建议: 本题最关键是要理解 虚拟头结点的使用技巧,这个对链表题目很重要。
题目链接:力扣

思路一:头结点存在可能是删除值的可能.

/**
 * 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!=nullptr && head->val == val)//while使用防止连续几个都是头结点为空
        {
            ListNode* cur = head;
            head = head->next;
            delete cur;
        }

        //头节点存在,并且不为空
        ListNode* cur1 = head;//注意:这个地方一定要进行相应的赋值,不能够直接操作head
        while(cur1!=nullptr && cur1->next!=nullptr)
        {
            if(cur1->next->val == val)
            {
                ListNode* tem = cur1->next;//这个地方也需要进行赋值,否则会出问题.
                cur1->next = cur1->next->next;
                delete tem;
            }
            else
            {
                cur1=cur1->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* dummynode = new ListNode(0);
        dummynode->next = head;
        //ListNode* head = dummynode;

        ListNode* cur = dummynode;
        while(cur->next!=nullptr)
        {
            
            if(cur->next->val == val)
            {
                ListNode* temp = cur->next;
                cur->next = cur->next->next;
                delete temp;
            }
            else 
            {
                cur = cur->next;
            }
        }
       
       head=dummynode->next;
       delete dummynode;
       return head;

    }
};

注意:内存回收机制,C++之中存在一个delete的内存删除过程,针对于指针而言.但是java之中存在一个自动回收内存的过程.
C++标准规定:delete空指针是合法的,没有副作用。所以我们一般在delete后就以为万事大吉了,其实这是不安全的。delete释放指针指向的那部分内存,并不是指针本身的内存,在进行delete之后,指针还是会指向那块内存,如果要没有清空,会出现***空间不能够访问的异常.

707.设计链表   

建议: 这是一道考察 链表综合操作的题目,不算容易,可以练一练 使用虚拟头结点

题目链接:力扣

这个地方需要注意的地方是更新边的过程,先更新哪个边.下面的代码是我自己编写的,我感觉没有错误,但是就是编译不出来,不知道啥原因.

class MyLinkedList {
public:


    //1.首先建立链表操作
    struct ListNode
    {
        int val;
        ListNode* next;
        ListNode(int val1,ListNode* next1 = nullptr)
        {
           val1 = val;
           next1 = next;

        }

    };    
    
    //2.声明大小和节点
    ListNode* dummyHead;
    int size;
    MyLinkedList() {
        dummyHead = new ListNode(0);
        size = 0;

    }
    
    int get(int index) {
        if(index < 0 || index >= size)
        {
            return -1;
        }
        ListNode* cur = dummyHead;
        while(index--)//直接将index进行一个减小的过程
        {
            cur = cur->next;

        }
        return cur->next->val;
    }
    
    void addAtHead(int val) {
        //注意头结点为空也是可以的
        ListNode* newHead = new ListNode(val);

        ListNode* cur = dummyHead;

        //注意插入的顺序,先是插入后面的元素,然后才是进行插入前面的元素
        newHead->next = cur->next;
        cur->next=newHead;

        //一定要注意
        size++;

    }
    
    void addAtTail(int val) {

      ListNode* newNode = new ListNode(val);
        ListNode* cur = dummyHead;
        while(cur->next != nullptr){
            cur = cur->next;
        }
        cur->next = newNode;
        size++;
        
    }
    
    void addAtIndex(int index, int val) {
        if(index<0||index>(size-1))
        {
            return;
        }
        ListNode* cur = dummyHead;
        ListNode* newHead = new ListNode(val);
        while(index--)
        {
            cur=cur->next;
        }
        newHead->next = cur->next;
        cur=newHead;
        size++;

    }
    
    void deleteAtIndex(int index) {
        if(index<0||index>(size-1))
        {
            return;
        }
        ListNode* cur = dummyHead;
        while(index--)
        {
            cur=cur->next;
        }
        ListNode* tem = cur->next;
        cur->next= cur->next->next;
        delete tem;
        tem = nullptr;
        size--;
    }
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

206.反转链表 

题目链接:力扣

本题有两种接法,一种是双指针解法,一种是进行递归求解.递归求解的方式参考意义不大,个人认为,因此这里只写双指针的解法.其实理解了很好实现,不理解就是很难去实现。

/**
 * 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* reverseList(ListNode* head) {
        ListNode* pre = nullptr;
        ListNode* cur = head;

        while(cur!=nullptr)
        {
            ListNode* tem= cur->next;
            cur->next=pre;
            pre=cur;
            
            cur=tem;


        }
        return pre;

    }
};

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

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

相关文章

代码随想录算法训练营第五十三天 | 子序列系列2

1143.最长公共子序列 文档讲解&#xff1a;代码随想录 (programmercarl.com) 视频讲解&#xff1a;动态规划子序列问题经典题目 | LeetCode&#xff1a;1143.最长公共子序列_哔哩哔哩_bilibili 状态&#xff1a;dp定义想不到&#xff0c;看了dp定义能写出后面部分。 思路 动规…

ab压力测试工具使用

AB测试工具使用 参考网址&#xff1a; https://pdai.tech/md/devops/linux/linux-ab-test.html 推荐 java 体系学习网址 https://pdai.tech/ 安装 基于 Linux 操作系统 &#xff0c; 在 centos7 中安装 ab 测试工具 yum -y install httpd-tools测试安装是否成功&#xff1a;…

【ISO14229_UDS刷写】-1-$34诊断服务RequestDownload理论部分

总目录&#xff1a;&#xff08;单击下方链接皆可跳转至专栏总目录&#xff09; 《UDS/OBD诊断需求编辑工具》总目录https://blog.csdn.net/qfmzhu/article/details/123697014 目录 1 $0x34 RequestDownload诊断服务描述 2 0x34服务请求消息 2.1 0x34服务请求消息定义 2.…

11.TMS320C5509V+Win10+CCS8开发环境搭建

一、简介 众所周知&#xff0c;相较于TMS320F28335&#xff0c;TMS320C5509V属于较老的平台&#xff0c;在新版本的CCS版本上支持一直是一个问题。 最基本的问题便是&#xff0c;无法新建基础工程。各开发版厂商提供的例程无法在CCS8上使用&#xff0c;只支持CCS3.3环境&…

chatgpt赋能python:Python分词库的介绍

Python 分词库的介绍 Python 分词库是一个用于将一段自然语言文本分解为单词序列的工具。这对于自然语言处理和文本分析来说是一个重要的工具。Python 分词库可以将大量的文本数据转化成机器可读的、易于处理的数据。在 SEO 优化方面&#xff0c;Python 分词库也起到了关键的作…

华为云安装与使用

华为云安装与使用 文章目录 华为云安装与使用下载地址修改 /etc/hosts设置 AK/SK/Endpoint查看桶名查看桶内文件通过 ./obsutil config -interactive 方式设置配置文件问题 obsutil 命令行快速使用操作步骤操作桶上传文件约束与限制参数说明更多上传示例 删除下载对象 Referenc…

数据库基础——2.MySQL的卸载安装及相关环境的配置

这篇文章我们来说一下MySQL的下载、安装、相关环境配置、可能遇见的问题及其解决方案、卸载等操作。 目录 1.查看已安装的 1.1 命令提示窗口下查看 1.2 文件目录下查看 2.Mysql的卸载 2.1卸载mysql 2.2 清理其他文件 3.MySQL的下载 3.1 介绍 3.2 软件下载 3.3 软件安…

python求解一阶线性偏微分方程通解举例

python求解一阶线性偏微分方程的通解举例 Python求解偏微分方程也是其一个应用方面&#xff0c;下面举例说明。 一、问题&#xff1a; 求一阶线性偏微分方程 x ∂ f ( x , y ) ∂ x − y ∂ f ( x , y ) ∂ y y 2 f ( x , y ) y 2 x\frac{{\partial f(x,y)}}{{\partial x}…

海康线扫相机平场校正/阴影校正教程

机器视觉海康visionmaster-字符快速识别,字符缺陷检测 为什么要对线阵相机进行平场矫正(PRNUC) 线阵相机需要平场矫正(PRNUC)主要是因为获取得图像有异常,如图像边缘亮度与中心亮度不一致情况等, 对于现场使用相机获取图像数据有较大影响,故而需要对线阵相机进行平场矫…

Linux网络服务:PXE高效批量网络装机

目录 一、理论 1.PXE批量网络装机概述 2.搭建 PXE 远程安装服务器 3.实现Kickstart无人值守安装 二、实验 1.搭建PXE远程安装服务器 2.安装Kickstart无人值守安装 3.安装图形化界面 三、问题 1.please complete all spokes before continuing 提示 一、理论 1.PXE批…

【Python】列表和字典

知识目录 一、写在前面✨二、列表应用三、字典应用四、总结撒花&#x1f60a; 一、写在前面✨ 大家好&#xff01;我是初心&#xff0c;希望我们一路走来能坚守初心&#xff01; 今天跟大家分享的文章是 Python函数式编程第二弹&#xff0c;再次以两个简单的例子带大家更好的…

Hbase高可用集群的搭建

高可用基于zookeeper zookeeper安装教程&#xff1a;集群上Zookeeper服务的搭建_EEEurekaaa&#xff01;的博客-CSDN博客 1.下载安装包 推荐去国内源进行安装 Index of /apache/hbase 下载版本时&#xff0c;注意hbase与Hadoop的版本对应关系 2.上传服务器并解压 4.配置环…

【ISO14229_UDS刷写】-2-$35诊断服务RequestUpload理论部分

总目录&#xff1a;&#xff08;单击下方链接皆可跳转至专栏总目录&#xff09; 《UDS/OBD诊断需求编辑工具》总目录https://blog.csdn.net/qfmzhu/article/details/123697014 目录 1 $0x35 RequestUpload诊断服务描述 2 0x35服务请求消息 2.1 0x35服务请求消息定义 2.2 …

2022中国大学生程序设计竞赛(CCPC)高职专场

一&#xff0c;期望 题意&#xff1a; 初始时你有1−n这n个正整数和一个空的序列&#xff0c;你准备玩一个往序列中加数字的无聊游戏。游戏进行n轮,在游戏的每一轮中你要向序列尾部加入一个还未被加入的数&#xff0c;最终的序列将会是一个长度为n的排列。在某一轮游戏开始前…

五、Docker仓库之https的registry搭建(二)

本节我们分享更多的实用的仓库搭建使用方式。包括支持https的registry、Harbor、nexus。 支持HTTPS的registry 准备站点证书&#xff08;测试使用&#xff0c;用一个自己的测试域名&#xff0c;配置本地hosts&#xff09; 如果你拥有一个公网域名&#xff0c;那很好&#xff…

ESP-01模块刷固件

ESP-01模块刷固件 0.前言一、准备二、烧写1.接线2.软件设置3.检验 0.前言 最近需要用esp-01模块作为wifi模块上云&#xff0c;但由于出厂自带固件太过老旧&#xff0c;经常会出现奇奇怪怪的警告&#xff0c;所以记录下如何给ESP-01刷写较新的固件。 一、准备 需要准备三个东西…

Python之并发编程一背景知识

一、开篇介绍 顾名思义&#xff0c;进程即正在执行的一个过程。进程是对正在运行程序的一个抽象。 进程的概念起源于操作系统&#xff0c;是操作系统最核心的概念&#xff0c;也是操作系统提供的最古老也是最重要的抽象概念之一。操作系统的其他所有内容都是围绕进程的概念展…

大型软件外包开发管理工具

大型软件项目涉及人员多&#xff0c;软件代码量大&#xff0c;业务复杂&#xff0c;因此需要借助软件工程的管理工具进行管理&#xff0c;否则容易隐入混乱。今天和大家分享这些工具&#xff0c;这些工具比较实用&#xff0c;在实际工作中使用广泛&#xff0c;希望对大家有所帮…

Linux常规基础配置

通过VMware成功安装RHEL7服务器后&#xff0c;为了能够正常使用&#xff0c;需要对其进行常规的一些基础配置&#xff0c;主要有&#xff1a;关闭防火墙与selinux&#xff0c;设置主机名&#xff0c;配置虚拟机IP地址使其能够与外网ping通&#xff0c;配置IP地址与主机名映射&a…

从小白到大神之路之学习运维第29天

第二阶段基础 时 间&#xff1a;2023年5月25日 参加人&#xff1a;全班人员 内 容&#xff1a; Apache服务 目录 一、基本信息 二、安装方法 三、配置方法 四、虚拟主机头 1&#xff1a;基于不同的IP地址 2&#xff1a;基于不同的端口 3&#xff1a;基于不同的域…