【力扣刷题】删除链表的倒数第 N 个结点、两两交换链表中的节点、随机链表的复制

news2024/10/1 7:42:36

在这里插入图片描述

🐌个人主页: 🐌 叶落闲庭
💨我的专栏:💨
c语言
数据结构
javaEE
操作系统
Redis

石可破也,而不可夺坚;丹可磨也,而不可夺赤。


刷题篇

  • 一、删除链表的倒数第 N 个结点
    • 1.1 题目描述
    • 1.2 思路分析
    • 1.3 代码演示
  • 二、两两交换链表中的节点
    • 2.1 题目描述
    • 2.2 思路分析
    • 2.3 代码演示
  • 三、随机链表的复制
    • 3.1 题目描述
    • 3.2 思路分析
    • 3.3 代码演示

一、删除链表的倒数第 N 个结点

1.1 题目描述

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。


在这里插入图片描述


在这里插入图片描述


1.2 思路分析

我的思路是先求出整个链表的长度,要删除倒数第n个节点,则将链表的长度减去n得到要删除的节点的前一个节点的索引,将链表长度减n+1得到要删除的节点的索引,定义两个指针,一个指针表示要删节点的前一个节点,另一个表示要删的节点,根据两个索引值对链表进行遍历,遍历索引值减1次就能得到索引对应的节点处,然后将要删节点的前一个节点的next指向要删的节点的next,完成倒数第n个节点的删除,当要删除的是第一个节点时(即删除倒数第链表长度个节点),直接改变头节点的位置即可。

1.3 代码演示

public ListNode removeNthFromEnd(ListNode head, int n) {
        //求出链表的长度
        int len = listLen(head);
        //如果是删除第一个节点,就是头删
        if(n == len) {
            head = head.next;
            return head;
        }
        //定义两个节点指针
        ListNode prev = head;
        ListNode del = head;
        //求出要删节点前的的节点位置
        int l = len - n;
        //求出要删除节点的位置
        int d = len - n + 1;
        //遍历链表找到这两个节点
        for(int i = 0;i < l - 1; i++) {
            prev = prev.next;
        }
        for(int j = 0;j < d - 1; j++) {
            del = del.next;
        }
        //删除节点
        prev.next = del.next;
        return head;
    }

    public int listLen(ListNode head) {
        int len = 1;
        ListNode cur = head;
        while(cur.next != null) {
            len++;
            cur = cur.next;
        }
        return len;
    }

二、两两交换链表中的节点

2.1 题目描述

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。


在这里插入图片描述


在这里插入图片描述


2.2 思路分析

按照题目来看,默认给定的链表节点值的个数是偶数(除去一个节点和空链表的情况),对这个链表的节点值进行两两交换,可以有如下分析:

  • 当链表为空或是只有一个节点时,返回链表头结点
  • 定义一个哨兵节点并将他的next指向链表头结点,定义一个辅助交换的节点tmp,它初始指向哨兵节点,当这个辅助节点的下一个不为空并且它的下一个的下一个不为空时进入循环,定义第一个节点指针指向tmp的next,定义第二个节点指针指向tmp.next.next,开始交换,就是将这两个节点的指向交换一下位置,循环遍历整个链表,最后返回哨兵位的下一个节点即头节点。

2.3 代码演示

public ListNode swapPairs(ListNode head) {
        if (head == null || head.next == null) {
            return head;
        }
        //定义哨兵节点
        ListNode prev = new ListNode(0);
        prev.next = head;
        //定义交换辅助节点
        ListNode tmp = prev;
        while(tmp.next != null && tmp.next.next != null) {
            //定义第一个节点指针
            ListNode start = tmp.next;
            //定义第二个节点指针
            ListNode end = tmp.next.next;
            //开始交换
            tmp.next = end;
            start.next = end.next;
            end.next = start;
            tmp = start;
        }
        return prev.next;
    }

三、随机链表的复制

3.1 题目描述

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
返回复制链表的头节点。
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
val:一个表示 Node.val 的整数。
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
你的代码 只 接受原链表的头节点 head 作为传入参数。

3.2 思路分析

开始看到这道题的时候我是很懵的状态,完全看不懂题目是什么意思,后来才慢慢理解,先来解释一下题目的要求:

  • 给定一个特殊的链表,就是普通的链表多加了一个节点,这个多加的节点随机指向链表上的某个节点或指向空,多个随机节点可以指向同一个节点,按我的判断,虽说这个随机节点的指向是“随机”的,但其实并不用太关注它的指向,因为题目给的链表中的所有节点的指向都已经确定了,只要将这个链表复制一份形成一个新链表就可以了。

接下来对这道题进行解题思路分析:

  • 因为是对链表进行拷贝,最终是会有两个不同的链表,可以考虑使用Map集合,在向集合中添加元素的时候,旧链表的节点作为键,同时这个键对应的值是新创建的节点,新创建的节点值就是旧链表的节点值,当遍历完链表,map集合中就收集了两个链表的信息;再次遍历链表,每次遍历根据map集合中的键(旧链表节点)找到值(新链表节点),再将当前节点的next指针(旧链表的第二个节点)作为键找出它在map集合中对应的值(新链表的第二个节点),将第一个值的next指向第二个值(就是将新链表形成链表结构),再根据当前节点的random(random节点指向是由旧链表提供好的)作为键拿到它在map集合中对应的值(就是新链表random所指向的节点),将它作为由map集合根据键找出来的新链表的节点的random的指向,最后返回head作为键找到的值(就是新链表的头节点)。

在这里插入图片描述


3.3 代码演示

public Node copyRandomList(Node head) {
        if (head == null) {
            return null;
        }
        Node cur = head;
        Map<Node,Node> map = new HashMap<>();
        //遍历链表,向map集合中添加原链表节点作为键和新链表节点作为值
        //并为新链表节点赋值
        while(cur != null) {
            map.put(cur,new Node(cur.val));
            cur = cur.next;
        }
        //重新指向头节点
        cur = head;
        //遍历map集合,在遍历的过程中更新新链表
        while(cur != null) {
            //更新map集合中的值的next指针
            map.get(cur).next = map.get(cur.next);
            //更新map集合中的值的random指针
            map.get(cur).random = map.get(cur.random);
            cur = cur.next;
        }
        return map.get(head);
    }

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

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

相关文章

一起学数据结构(12)——归并排序的实现

1. 归并排序原理&#xff1a; 归并排序的大概原理如下图所示&#xff1a; 从图中可以看出&#xff0c;归并排序的整体思路就是把已给数组不断分成左右两个区间&#xff0c;当这个区间中的数据数量到达一定数值时&#xff0c;便返回去进行排序&#xff0c;整体的结构类似二叉树…

【Master公式】对于这一类符合的递归可以直接确定时间复杂度

Master公式 T(N) a T(N/b) O(N^d) 对于这一类符合的递归可以直接确定时间复杂度 a,b,c为常数 1、子问题调用了a次 2、子问题的规模一致&#xff0c;N/b指每个子问题处理总规模/b个规模&#xff08;只看规模&#xff0c;常数个忽略&#xff0c;如L,mid,mid1,R&#xff09; 3、…

【Airflow】构建爬虫任务系统

爬虫脚本太多了需要进行管理一下&#xff0c;领导决定使用airflow 我了解了一下这个平台是用来做任务调度。 是一个ETL工具 ETL是将业务系统的数据经过抽取、清洗转换之后加载到数据仓库的过程 这里是一个github的地址 https://github.com/apache/airflow 这里是官方文档 http…

手机桌面待办事项APP推荐

每天&#xff0c;我们每个人都面临着繁琐的事务和任务&#xff0c;而手机成了我们日常生活中不可或缺的伙伴。手机上的待办事项工具像一个可靠的助手&#xff0c;可以帮助我们更好地记录、管理和完成任务。在手机桌面上使用的待办事项APP推荐用哪一个呢&#xff1f; 手机是我们…

【QT】信号和槽

一、前置示例代码 main.cpp #include "widget.h"#include <QApplication>int main(int argc, char *argv[]) {QApplication a(argc, argv); // 应用程序对象a&#xff0c;在Qt中&#xff0c;应用程序对象&#xff0c;有且仅有一个。Widget w; // 窗口对…

python sqlalchemy(ORM)- 02 表关系

文章目录 表关系ORM表示 1v1ORM表示 1vm 表关系 1:1&#xff0c;表A 中的一条记录&#xff0c;仅对应表B中的一条记录&#xff1b;表B的一条记录&#xff0c;仅对应表A的一条记录。1:m&#xff0c;表A中的一条记录&#xff0c;对应表B中的多条记录&#xff0c;表B中的一条记录…

编译原理-词法分析器

文章目录 对于词法分析器的要求概念词法分析器的功能和输出形式 词法分析器的设计词法分析器的结构单词符号的识别&#xff1a;超前搜索状态转换图 正规表达式和有限自动机正规式和正规集确定有限自动机&#xff08;DFA&#xff09;非确定有限自动机&#xff08;NFA&#xff09…

多级缓存入门

文章目录 什么是多级缓存JVM进程缓存环境准备安装MySQL导入Demo工程导入商品查询页面 初识Caffeine Lua语法初识Lua第一个lua程序变量和循环Lua的数据类型声明变量循环 条件控制、函数函数条件控制 多级缓存安装OpenRestyOpenResty快速入门反向代理流程OpenResty监听请求编写it…

scrapy的安装和使用

一、scrapy是什么&#xff1a;Scrapy是一个为了爬取网站数据&#xff0c;提取结构性数据而编写的应用框架&#xff0c;可以应用在包括数据挖掘&#xff0c;信息处理或存储历史数据等一系列的程序 二、scrapy的安装&#xff1a;pip install scrapy -i https://pypi.douban.com/…

CURL简单使用

前言 最近做项目&#xff0c;需要服务器实现网络是否通畅&#xff0c;比如通过健康检查接口&#xff0c;但是只能linux服务器测试&#xff0c;很可能还需要测试h2&#xff0c;所以想到了curl&#xff0c;整理一版简单用法。 curl 实际上curl是有官网的&#xff0c;只不过比较…

java中的异常,以及出现异常后的处理【try,catch,finally】

一、异常概念 异常 &#xff1a;指的是程序在执行过程中&#xff0c;出现的非正常的情况&#xff0c;最终会导致JVM的非正常停止。 注意: 在Java等面向对象的编程语言中&#xff0c;异常本身是一个类&#xff0c;产生异常就是创建异常对象并抛出了一个异常对象。Java处理异常的…

C语言-面试题实现有序序列合并

要求&#xff1a; a.输入两个升序排列的序列&#xff0c;将两个序列合并为一个有序序列并输出。 数据范围&#xff1a; 1≤n,m≤1000 1≤n,m≤1000 &#xff0c; 序列中的值满足 0≤val≤30000 输入描述&#xff1a; 1.输入包含三行&#xff0c; 2.第一行包含两个正整数n, m&am…

Modbus协议详解4:RTU帧 ASCII帧的差错校验

前面已经分析过RTU帧和ASCII帧的报文区别&#xff0c;细心的朋友应该会发现在两种不同的报文传输模式下都有一个共同的组成部分——差错校验。 这个差错校验在RTU模式和ASCII模式下也不是不相同的。看下面的对比&#xff1a; RTU模式的差错校验&#xff1a; ASCII模式的差错校验…

对GRUB和initramfs的小探究

竞赛时对操作系统启动过程产生了些疑问&#xff0c;于是问题导向地浅浅探究了下GRUB和initramfs相关机制&#xff0c;相关笔记先放在这里了。 内核启动流程 在传统的BIOS系统中&#xff0c;计算机具体的启动流程如下&#xff1a; 电源启动&#xff1a;当计算机的电源打开时&…

CPU眼里的C/C++:1.2 查看变量和函数在内存中的存储位置

写一个很简单的 c 代码&#xff0c;打印一些“地址”&#xff0c; 也就是变量、函数的“存储位置”&#xff1a;当程序被加载到内存后&#xff0c;它们具体是存在哪里&#xff0c;可以用精确的数值来表示&#xff0c;这就是内存地址。 https://godbolt.org/z/Ghh9ThY5Y #inc…

电解电容寿命与哪些因素有关?

电解电容在各类电源及电子产品中是不可替代的元器件&#xff0c;这些电子产品中由于应用环境的原因&#xff0c;使它成为最脆弱的一环&#xff0c;所以&#xff0c;电解电容的寿命也直接影响了电子产品的使用寿命。 一、电解电容失效模式与因素概述 铝电解电容器正极、负极引出…

Java实现ORM第一个api-FindAll

经过几天的业余开发&#xff0c;今天终于到ORM对业务api本身的实现了&#xff0c;首先实现第一个查询的api 老的C#定义如下 因为Java的泛型不纯&#xff0c;所以无法用只带泛型的方式实现api&#xff0c;对查询类的api做了调整&#xff0c;第一个参数要求传入实体对象 首先…

android——自定义控件(编辑框)、悬浮窗

一、自定义编辑框 效果图&#xff1a; 主要的代码为&#xff1a; class EditLayout JvmOverloads constructor(context: Context, attrs: AttributeSet? null, defStyleAttr: Int 0 ) : ConstraintLayout(context, attrs, defStyleAttr) {private var editTitle: Stringpr…

Android12 启动页适配

印象中&#xff0c;在2022年末接到了一个针对Android12启动页适配的需求&#xff0c;当时也使用了一些适配方案&#xff0c;也写了一个Demo&#xff0c;但是最终没有付诸适配行动&#xff1b;当然并不是适配失败&#xff0c;而是根据官方适配方案适配后太丑了… 1024纪念文章&a…

Java中的CAS简述

目录 1、CAS是什么 2、CAS的生活化例子 3、Java中的atomic包 4、unsafe类 5、CAS的缺点及解决方案 小结 1、CAS是什么 CAS&#xff08;Compare and Swap&#xff09;是一种并发编程中的原子操作&#xff0c;用于实现多线程环境下的无锁同步。它是一种乐观锁的实现方式&a…