代码随想录算法训练营第三天| 203. 移除链表、707. 设计链表、206.反转链表

news2025/1/11 21:06:53

977 有序数组的平方

题目链接:203 移除链表元素

介绍

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

思路一

  • 如果要被删除的元素是非头节点,只需要找到前一个节点,然后让前一个节点的下一个指向当前元素的下一个节点。

  • 如果要被删除的是头节点,将头节点head后移(head=head->next)

//先判断头节点不为空并且头节点指向的值是要删除的target
while(head!=NULL&&head->val=target){ //while是一个持续移动的过程
    head=head->next;//删除头节点
    //若是c++ 需要对删除的节点进行内存释放
}
cur = head; //每次检查cur->next是不是等于target
while(cur!=NULL&&cur-next!=NULL){
    if(cur->next->value == target){
        cur->next = cur->next->next;
    }else{
        cur = cur->next;
    }
}
return head;

思路二—虚拟头节点

规则统一:只需要找到前一个节点,然后让前一个节点的下一个指向当前元素的下一个节点。

注意—遍历列表的时候,头节点的指针是不能改变的,要定义一个临时的指针对链表进行删除操作

//定义一个虚拟头节点
dummyhead = new (节点);
dummyhead->next = head;
cur = dummyhead;//若删除的是真实的头节点,必须要知道真实头节点的上一个元素,也就是虚拟头节点
while(cur->next!=NULL){
    if(cur->next->val==target){
        cur->next = cur->next->next;
    }else{
        cur = cur->next
    }
}
return dummyhead->next;

代码

/**
 * 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){
            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;
      ListNode* cur = dummyHead;
      while(cur->next!=NULL){
        if(cur->next->val == val){
            ListNode* tmp = cur->next;
            cur->next = cur->next->next;
            delete tmp;
        }else{
            cur = cur->next;
        }
      }
      return dummyHead->next;
    }
};

707 设计链表

题目链接:707设计链表

介绍

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

在链表类中实现这些功能: n从0开始

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。获取第n个节点

  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。头部插入节点

  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。尾部插入节点

  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。第n个节点前插入节点

  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。删除第n个节点

思路

这里统一使用虚拟头节点的方式,从而更方便对链表进行增删改查操作。

获取第n个节点(n从0开始)

n<0不合法 n>size-1不合法
定义一个遍历指针cur指向头节点(操作完链表后要返回头节点head)
cur = dummyhead->next;
while(n){
    cur = cur->next;
    n--;
}
return cur->val

头部插入节点

newNode = new node()
//dummyhead是虚拟头节点
newNode->next = dummyhead->next
dummyhead->next = newNode
size++

尾部插入节点

newNode = new node() //定义newNode时,默认newNode->next=NULL
//找尾部的节点--当前遍历节点cur要指向尾部节点
cur = dummyhead
while(cur->next!=NULL){ //直到找到cur->next=NULL位置
    cur = cur->next
}
//newNode->next = cur->next
cur->next = newNode
size++

第n个结点前插入结点

//要找到第n个结点前一个的位置---cur
newNode = new node()
cur = dummyhead
while(n){
    cur = cur->next
    n--
}
newNode->next = cur->next;
cur->next = newNode;

删除第n个结点

//首先判断n的合法性
//然后还是要找到第n个节点前一个的位置
//第n个节点一定是curr->next
cur = dummyhead
while(n){
    cur = cur->next
    n--
}
curr->next = curr->next->next

代码

class MyLinkedList {
public:
 // 定义链表节点结构体
      struct LinkedNode {
        int val;
        LinkedNode* next;
        LinkedNode(int val):val(val), next(nullptr){}
    };

    // 初始化链表
       MyLinkedList() {
         _dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
         _size = 0;
    }
    
    int get(int index) {
        if(index >(_size-1)||index<0){
            return -1;
        }
        LinkedNode* cur = _dummyHead->next;
        while(index){
            cur = cur->next;
            index--;
        }
        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!=nullptr){
            cur =cur->next;
        }
        cur->next = newNode;
        _size++;
    }
    
    void addAtIndex(int index, int val) {
        if(index >_size) return;
        if(index<0) index=0;
        LinkedNode* newNode = new LinkedNode(val);
        LinkedNode* cur = _dummyHead;
        while(index){
            cur = cur->next;
            index--;
        }
        newNode->next = cur->next;
        cur->next = newNode;
        _size++;
    }
    
    void deleteAtIndex(int index) {
        if(index >=_size || index < 0){
            return;
        }
        LinkedNode* cur = _dummyHead;
        while(index){
            cur = cur->next;
            index--;
        }
        LinkedNode* tmp = cur->next;
        cur->next = cur->next->next;
        delete tmp;
        _size--;
    }
    private:
        int _size;
        LinkedNode* _dummyHead;
};

/**
 * 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 反转链表

题目链接:206反转链表

介绍

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

思路

思路一:双指针写法

首先进行初始化:current=head   pre=NULL 能够让翻转后的head->null
遍历链表: 遍历结束条件-->curr=NULL
while(curr!=NULL){
 //使用一个临时指针在翻转赋值之前记录curr的下一个结点
    temp = curr->next;
 //翻转赋值
    curr->next=pre;
 //curr和pre整体后移
    pre = curr;
    curr = temp;
}
//跳出循环时,curr指向NULL,pre指向了新链表的头节点
return pre;

思路二:递归写法

//206
reverseList(head){
    return reverse(head,NULL)
}
reverse(curr,pre){
    if(curr==NULL)
        return pre;
    temp = curr->next;
    curr->next = pre;
    revrse(temp,curr)
}

代码

/**
 * 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* curr = head;
        ListNode* pre = nullptr;
        ListNode* tmp = nullptr;
        while(curr!=nullptr){
            tmp = curr->next;
            curr->next = pre;
            pre = curr;
            curr = tmp;
        }
        return pre;
    }
};
/**
 * 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* reverse(ListNode* curr,ListNode* pre){
        if(curr==NULL) return pre;
        ListNode* temp = curr->next;
        curr->next = pre;
        //pre = curr
        //curr = temp
        return reverse(temp,curr);
    }
    ListNode* reverseList(ListNode* head) {
        return reverse(head,NULL);
    }
};

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

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

相关文章

MySQL之幻读问题

MySQL之幻读问题 导读 在进入今天的主题之前必须先了解事务的四大特性ACID、MVCC、事务隔离级别&#xff08;具体的自行查询&#xff09;&#xff0c;其中I&#xff08;Isolation&#xff09;隔离性所产生的问题涉及到的事务隔离分为不同级别&#xff0c;包括读未提交&#x…

python+pytest接口自动化(7)-cookie绕过登录(保持登录状态)

在编写接口自动化测试用例或其他脚本的过程中&#xff0c;经常会遇到需要绕过用户名/密码或验证码登录&#xff0c;去请求接口的情况&#xff0c;一是因为有时验证码会比较复杂&#xff0c;比如有些图形验证码&#xff0c;难以通过接口的方式去处理&#xff1b;再者&#xff0c…

Java多线程——线程安全、synchronized、volatile关键字以及多线程案例

文章目录前言一、线程安全—多线程不可避免的风险&#xff01;1、线程不安全的示例2、线程不安全的原因二、synchronized关键字1.synchronized的特性1&#xff09;互斥2&#xff09;刷新内存3&#xff09;可重入2、synchronized使用示例3、Java标准库中的线程安全类三、volatil…

【巨人的肩膀】JAVA面试总结(四)

&#x1f4aa;、JVM 目录&#x1f4aa;、JVM1、说一下JVM的主要组成部分及其作用2、什么是JVM内存结构&#xff08;谈谈对运行时数据区的理解&#xff09;3、堆和栈的区别是什么4、堆中存什么&#xff1f;栈中存什么&#xff1f;5、为什么不把基本类型放堆中呢&#xff1f;6、为…

理论上BI软件适配任何行业,但为什么有些行业做不了?

BI商业智能是一种通用的数据类技术解决方案。理论上来说&#xff0c;BI商业智能的核心是数据。只要企业有数据累积&#xff0c;就可以在BI软件上展开一系列的数据开发&#xff0c;获取决策所需的数据依据。但在现实中&#xff0c;却会发现有些BI软件对特定的行业束手无策&#…

【站外SEO】如何利用外部链接来提高你的网站排名

随着互联网的快速发展&#xff0c;越来越多的企业开始注重SEO优化&#xff0c;以提升自己的网站排名&#xff0c;增加流量和曝光度。 而站外SEO作为SEO的重要组成部分&#xff0c;对于提升网站排名具有不可忽视的作用。 站外SEO主要是通过外部链接来提高网站的排名。而GPB外链…

4EVERLAND 的 IPFS Pinning 服务:4EVER Pin

我们很高兴地宣布 4EVERLAND Storage 的一个令人兴奋的补充&#xff0c;即 4EVER Pin。什么是 4EVER Pin&#xff1f;您可能已经知道星际文件系统或IPFS是一个分布式存储网络&#xff0c;来自世界各地的计算机组成节点共享数据。通常&#xff0c;在IPFS中获取一条数据时&#x…

3/3操作系统作业

目录 1.前趋图和程序执行 &#xff08;1&#xff09;前驱图 &#xff08;2&#xff09;程序的顺序执行 &#xff08;3&#xff09;程序的并发执行 2.进程的描述 &#xff08;1&#xff09;进程的定义与特征 ​编辑​编辑&#xff08;2&#xff09;进程控制块​编辑 &…

ESP32设备驱动-GUVA-S12SD紫外线检测传感器驱动

GUVA-S12SD紫外线检测传感器驱动 文章目录 GUVA-S12SD紫外线检测传感器驱动1、GUVA-S12SD介绍2、硬件准备3、软件准备4、驱动实现1、GUVA-S12SD介绍 GUVA-S12SD 紫外线传感器芯片适用于检测太阳光中的紫外线辐射。 它可用于任何需要监控紫外线量的应用,并且可以简单地连接到任…

DebugView在Vs + Qt 应用程序中的使用

1.准备头文件mylog.h #pragma once #ifndef _MYLOG_H_ #define _MYLOG_H_#include <windows.h> #include <tchar.h>#define DP0(fmt) {TCHAR sOut[256];_stprintf_s(sOut,_T(fmt));OutputDebugString(sOut);} #define DP1(fmt,var) {TCHAR sOut[256];_stprintf_s(…

【Java】CompletableFuture 并发顺序调度

前言 Java CompletableFuture 提供了一种异步编程的方式&#xff0c;可以在一个线程中执行长时间的任务&#xff0c;而不会堵塞主线程。 和Future相比&#xff0c;CompletableFuture不仅实现了Future接口&#xff0c;也实现了 CompletionStage接口。Future接口不用多说&#…

react renderProps学习记录

react renderProps学习记录1.引入2.改一下呢3.再改一下呢4.总结一下如何向组件内部动态传入带内容的结构(标签)?children propsrender props1.引入 上代码&#xff1a; import React, { Component } from react import ./index.css export default class Parent extends Com…

【云原生】K8S调度约束

一、调度约束 Kubernetes 是通过 List-Watch&#xff08;监控&#xff09; 的机制进行每个组件的协作&#xff0c;保持数据同步的&#xff0c;每个组件之间的设计实现了解耦。 用户是通过 kubectl 根据配置文件&#xff0c;向 APIServer 发送命令&#xff0c;在 Node 节点上面…

ANR系列(二)——ANR监听方案之SyncBarrier

前言 在项目中经常遇到了手机假死问题&#xff0c;无规律的偶现问题&#xff0c;大量频繁随机操作后&#xff0c;便会出现假死&#xff0c;整个应用无法操作&#xff0c;不会响应事件&#xff0c;会发生各种奇怪的ANR&#xff0c;且trace不固定。而SyncBarrier是其中的罪魁祸首…

RabbitMq(具体怎么用,看这一篇即可)

RabbitMq汇总1.RabbitMq的传统实现方式2.SpringAMQP简化RabbitMq开发2.1 基本消息队列&#xff08;BasicQueue&#xff09;2.2 工作消息队列&#xff08;WorkQueue&#xff09;2.3 发布订阅 -- 广播&#xff08;Fanout&#xff09;2.4 发布订阅 -- 路由&#xff08;Direct&…

2024级浙江大学MBA提面申请流程参考

近年来浙大MBA项目的招生一直都有提前批面试的环节&#xff0c;而且每年在申请政策方面也会做出一些微调&#xff0c;但大的方面不会做调整&#xff0c;2024年MBA提面申请即将开始&#xff0c;对此杭州达立易考教育结合2023年的情况为大家梳理出来基本的申请流程和批次参考&…

【Spring Boot】Spring Boot以Repository方式整合Redis

1 简介 Redis是高性能的NoSQL数据库&#xff0c;经常作为缓存流行于各大互联网架构中。本文将介绍如何在Springboot中整合Spring Data Redis&#xff0c;使用Repository的方式操作。 代码结构如下&#xff1a; 2 整合过程 2.1 安装Redis数据库 为了节省时间&#xff0c;就直…

为什么很多计算机专业大学生毕业后还会参加培训?

基于IT互联网行业越来越卷的现状&#xff0c;就算是科班出身&#xff0c;很多也是达不到用人单位的要求。面对这样的现实情况&#xff0c;有的同学会选择继续深造&#xff0c;比如考个研&#xff0c;去年考研人数457万人次&#xff0c;可见越来越的同学是倾向考研提升学历来达到…

管道。环境变量和常用命令

文章目录管道与文件重定向的区别举例环境变量使用自己编写的程序像命令符一样常用命令grepagwctree . -acutsortmorehistory管道 管道类似于重定向&#xff0c;但是又不太一样&#xff0c;管道可以连接好几个&#xff0c;把第一个的输出当成第二个的输入&#xff0c;第二个的输…

实践Spring5 响应式编程框架WebFlux

WebFlux 以 Reactor 库为基础, 基于异步和事件驱动&#xff0c;可以让我们在不扩充硬件资源的前提下&#xff0c;提升系统的吞吐量和伸缩性。一、什么是 Spring WebFlux了解 WebFlux ,首先了解下什么是 Reactive Streams。Reactive Streams 是 JVM 中面向流的库标准和规范&…