代码随想录-链表

news2024/11/24 11:58:55

基础知识

链表是一种通过指针串联在一起的线性结构。在内存中不是连续分布的,分配机制取决于操作系统内存管理。

类型

三种类型:单链表、双链表、循环链表

单链表:每个节点由两部分组成,数据域和指针域(存放指向下一个节点的指针),最后一个节点的指针域指向NULL。

双链表:每个节点有两个指针域( prec 和 next ),分别指向上一个和下一个节点,可以向前查询,也可以向后查询。

循环链表:首尾相连,可以解决约瑟夫环问题。

链表的c++定义

//单链表
struct ListNode {
    int val;
    ListNode *next;
    //构造函数
    ListNode (int x): val(x), next(nullptr) {}
};

重写构造函数,可以直接给 val 赋值:

ListNode *head = new ListNode(5);

使用默认函数不能直接赋值:

ListNode *head = new ListNode();
head->val = 5;

指针的简单知识

如下:ListNode* p = new ListNode()

不管是ListNode* p 还是ListNode *p,它的类型都是ListNode *,p是变量名,用来存储ListNode类型数据的地址。

C语言重点——指针篇(一篇让你完全搞懂指针) - 知乎 (zhihu.com)

移除元素

在这里插入图片描述

移除元素有两种方法:用/不用虚拟头节点

不用虚拟头节点

删除头节点的情况要单独讨论

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
		//删除头节点
        while (head != NULL && head -> val == val) {
            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;
    }
};

用虚拟头节点

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
		ListNode* dummyNode = new ListNode(0); //创建
        dummyNode -> next = head;
        ListNode* cur = dummyNode;
        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 = dummyNode -> next;
        delete dummyNode;
        return head;
    }
};

设计链表

在这里插入图片描述

这题真难,但真的顶。

自己写出来一堆错,看着题解改了好久

class MyLinkedList {
public:
    // 定义结构体
    struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val): val(val), next(nullptr) {}
    };
    // 初始化链表
    MyLinkedList() {
		_size = 0;
        _dummyHead = new LinkedNode(0);
    }
    // 根据索引获取元素
    int get(int index) {
		// 若值不合理,返回-1
        if (index > (_size - 1) || index < 0) {
            return -1;
        }
        LinkedNode* cur = _dummyHead->next;
        while (index--) {
            cur = cur->next;
        }
        return cur->val;
    }
    // 在头部添加新节点
    void addAtHead(int val) {
		LinkedNode* newNode = new LinkedNode(val);
        newNode->next = _dummyHead->next;
        _dummyHead->next = newNode;
        _size++;
    }
    // 在尾部添加新节点
    void addAtTail(int val) {
		LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while (cur->next != NULL) {
            cur = cur->next;
        }
        cur->next = newNode;
        _size++;
    }
    // 在Index前插入新节点
    void addAtIndex(int index, int val) {
		if (index > _size) { // 若等于size,就插入size-1,就是尾部。若小于0,就插入头部
            return; // 不作处理
        }
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while (index--) {
            cur = cur->next;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        _size++;
    }
    // 删除Index的节点
    void deleteAtIndex(int index) {
		if (index >= _size || index < 0) {
            return;
        }
        LinkedNode* cur = _dummyHead;
        while (index--) {
            cur = cur->next;
        }
        // 要删的是下一个节点
        LinkedNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        _size--;
    }
    void printLinkedList() {
        LinkedNode* cur = _dummyHead;
        while (cur->next != NULL) {
            cout << cur->next->val << " ";
            cur = cur->next;
        }
        cout << endl;
    }
private:
    int _size;
    LinkedNode* _dummyHead;
};

反转链表

在这里插入图片描述

两种方法:双指针法、递归法

双指针法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
		ListNode* pre = NULL; // 指向前一个结点
        ListNode* tmp; // 指向下一个结点
        ListNode* cur = head;
        while (cur) {
            tmp = cur->next; // 保存下一个结点
            cur->next = pre; // 反转
            // 循环
            pre = cur;
            cur = tmp;
        }
        return pre;
    }
};

递归法

与双指针完全相同的逻辑,只是写法不同

class Solution {
public:
    ListNode* reverse(ListNode* pre, ListNode* cur) {
        if (cur == NULL) return pre;
        ListNode* tmp = cur->next;
        cur->next = pre;
        return reverse(cur, tmp); // 这里就是循环
    }
    ListNode* reverseList(ListNode* head) {
		return reverse(NULL, head); // 初始化赋值
    }
};

删除倒数第n个节点

在这里插入图片描述

用一种非常美妙的双指针法,根本想不到

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
		ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* fast = dummyHead;
        ListNode* slow = dummyHead;
        // fast先走
        while (n-- && fast != NULL) {
            fast = fast->next;
        }
        // fast再走一步,因为要指向前一个结点,好删
        fast = fast->next;
        // fast和slow一起走
        while (fast != NULL) {
            fast = fast->next;
            slow = slow->next;
        }
        ListNode* tmp = slow->next;
        slow->next = slow->next->next;
        delete tmp;
        return dummyHead->next;
    }
};

环形链表

在这里插入图片描述

双指针法

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while (fast != NULL && fast->next != NULL) {
            // fast走两步,slow走一步
            fast = fast->next->next;
            slow = slow->next;
            // 二者相遇
            if (fast == slow) {
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index1; // 有环的情况
            }
        }
        return NULL; // 无环的情况
    }
};

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

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

相关文章

注解与反射

1、注解&#xff08;Annotation&#xff09; 1.1、何为注解&#xff1f; 注解&#xff08;Annotation&#xff09;是从JDK5.0开始引入的技术&#xff0c;以注解名在代码中存在&#xff0c;例如&#xff1a; Override&#xff1a;限定重写父类方法&#xff0c;该注解只能用于方…

Word控件Spire.Doc 【文本框】教程(5): 插入、读取和删除表格

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下&#xff0c;轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具&#xff0c;专注于创建、编辑、转…

提问超时~Zabbix Meetup成都站棒在哪里?

图片 2023年5月13日&#xff0c;迎着初夏灿烂的阳光&#xff0c;Zabbix Meetup首次在成都举办。本次活动吸引了来自Zabbix社区用户、合作伙伴等约50余位伙伴热情参与&#xff0c;倾听来自原厂培训师、社区资深用户们关于Zabbix的精彩内容分享。还有定制周边礼品和晚宴深入交流…

防火墙之iptables

防火墙之iptables 一.iptables概述 Linux 系统的防火墙 &#xff1a;IP信息包过滤系统&#xff0c;它实际上由两个组件netfilter 和 iptables组成。 主要工作在网络层&#xff0c;针对IP数据包。体现在对包内的IP地址、端口、协议等信息的处理上。二.netfilter/iptables 关系…

《终身成长》笔记二——失败挫折的意义

目录 经典摘录 思维模式改变了失败的意义/如何看待失败与成功 思维模式与抑郁症 努力后还是失败的事实会让自己找不到借口&#xff0c;是固定型思维模式者们最大的恐惧 问与答 经典摘录 思维模式改变了失败的意义/如何看待失败与成功 《纽约时报》上的一篇文章指出的&…

学生档案管理系统(SpringBoot,SSM,Maven,H-UI,Mysql)

【项目功能介绍】 本系统包含学生,后台管理员二种角色的用户 学生的功能包含: 登录,退出,修改密码,用户信息查看与修改,首页信息展示,轮播图,栏目及栏目文章列表,我的课程,我的课表,我的成绩,意见反馈,我的意见反馈。 后台管理员的功能包含: 登录,退出,修改密码,管理员管理,…

【计算机组成原理】实验一

文章目录 实验一 数据传送实验1. 实验目的2. 实验仪器3. 原理概述4. 实验内容步骤4.1 手动实验环境的建立4.2 手控传送实验 5. 实验结论及问题讨论 实验一 数据传送实验 1. 实验目的 2. 实验仪器 3. 原理概述 4. 实验内容步骤 4.1 手动实验环境的建立 1)初始待令状态 上电或…

监控kafka topic,钉钉报警

1、需求的诞生 前几天公司我们部门需要演示一个应用&#xff0c;应用依赖kafka的数据&#xff0c;但是kafka的数据来自其他部门的投递。 一些原因导致数据无法给到&#xff0c;导致我们部门的演示也很有问题&#xff0c;所以想做一个简单的kafka topic的监控&#xff0c;在没…

内网渗透之权限维持-黄金白银票据隐藏账户远控-RustDeskGotoHTTP

0x01权限维持-隐藏用户 CreateHiddenAccount工具 CreateHiddenAccount -u test -p Psswrd用户管理能查看到&#xff0c;命令查看看不到&#xff0c;单机版无法删除(不在任何组)&#xff0c;域环境(在administrator组中)可以删除 0x02权限维持-黄金白银票据 ⻩⾦票据⽣成攻…

捷威信keithley吉时利2410数字源表 销售回收KEITHLEY2470新款源表

吉时利Keithley 2410 /2470高压源表/数字源表 产品概览 Keithley 2410 高压源表专为需要紧密耦合源和测量的测试应用而设计。Keithly 2410 提供精密电压和电流源以及测量功能。它既是高度稳定的直流电源&#xff0c;又是真正的仪器级 5-1/2 数字万用表。电源特性包括低噪声、…

three.js实现拖拽生成模型场景

THREE.js 可以实现很多web 3D的效果&#xff0c;最近想实现一个拖拽生成场景的功能&#xff0c;主要用到拖拽API,draggable 的几个事件来实现&#xff0c;拖拽模型时记录模型属性&#xff0c;释放到画布时生成当前屏幕坐标对应的焦点上&#xff0c;最后生成模型。 <!DOCTYP…

增量更新和原始快照

三色标记法 2.1 基本算法 要找出存活对象&#xff0c;根据可达性分析&#xff0c;从GC Roots开始进行遍历访问&#xff0c;可达的则为存活对象&#xff1a; 最终结果&#xff1a;A/D/E/F/G 可达 我们把遍历对象图过程中遇到的对象&#xff0c;按“是否访问过”这个条件标记成…

【LeeCode】每日一题:复制带随机指针的链表

​&#x1f47b;内容专栏&#xff1a;《LeetCode刷题专栏》 &#x1f428;本文概括&#xff1a; 138.复制带随机指针的链表 &#x1f43c;本文作者&#xff1a;花 碟 &#x1f438;发布时间&#xff1a;2023.5.18 ​复制带随机指针的链表 力扣链接-> 138.复制带随机指针的链…

VS2019新建WebService/Web服务/asmx并通过IIS实现发布和调用

场景 对接第三方系统提供接口文档中显示为asmx接口 访问接口返回数据格式为 xml中的数据格式为json数据。 需要在本地新建并模拟调试环境。 注&#xff1a; 博客&#xff1a;霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主 实现 1、WebService WebService…

LeetCode刷题 --- 链表

定义一个node节点 class ListNode {int val;ListNode next;ListNode() {}ListNode(int val) {this.val val;}ListNode(int val, ListNode next) {this.val val;this.next next;} } 206 反转链表 题目&#xff1a;给你单链表的头节点 head &#xff0c;请你反转链表&#x…

【FAQ】视频编辑服务常见问题及解答

Q1问题描述 1、 访问贴纸等素材的时候提示“网络异常&#xff0c;请重试”怎么办&#xff1f; 2、 使用AI能力时&#xff0c;提示“errorCode:20124 errorMsg:Method not Allowed”&#xff1f; 解决方案 请做以下检查&#xff1a; 1、 在代码中检查鉴权信息是否已设置。如…

AI法律助手:ChatGPT如何提供智能化解决方案

日常生活中&#xff0c;民事纠纷不可避免&#xff0c;涉及到多种问题&#xff0c;如合同纠纷、劳动纠纷、婚姻家事、民间借贷、交通事故、工伤赔偿、房屋租赁等。解决这些问题&#xff0c;需要花费大量时间和精力&#xff0c;但现在&#xff0c;我们有了一种全新的解决方案&…

蓝库云:建立智慧零售,零代码技术能起到什么作用

随着科技的进步更多智能化的技术及应用融入我们生活中&#xff0c;例如零售行业在现代零售和传统零售的区别不仅在于营销策略、销售方式、销售渠道以及运营模式等方面&#xff0c;更多是在现代零售则更注重数字化营销&#xff0c;发挥社交媒体和电子商务渠道的作用&#xff0c;…

“前端”工匠系列(二):合格的工匠,怎么做好价值落地 | 京东云技术团队

一、“技术鄙视链&#xff1f;” 如果你是一个技术人&#xff0c;相信都知道技术圈有个相互的鄙视链&#xff0c;这个链条从技术人自己认知的角度在以业务价值为中心嵌套的一层一层的环&#xff0c;就像洋葱&#xff0c;具体的描述这里不赘述了。 出门左拐随便抓住一个人问一…

RabbitMQ应用问题——消息补偿机制以及代码示例

RabbitMQ应用问题——消息补偿机制以及代码示例 RabbitMQ应用问题 消息可靠性的保障 消息补偿机制 详细说明 这里使用了简单的代码进行演示&#xff0c;订单的消费者没有写&#xff0c;在订单的消费同时&#xff0c;发送一条增加积分消息到积分队列。 详细流程途中都有注明…