代码随想录算法训练营第4天 | 24. 两两交换链表中的节点 , 19.删除链表的倒数第N个节点 , 面试题 02.07. 链表相交 , 142.环形链表II

链表知识基础

文章链接:https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#

24. 两两交换链表中的节点

题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/
使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。

思路:使用虚拟头结点

设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除了。
然后注意一下,就是while里面,判断的条件有两个,pre.next != null && pre.next.next != null,才可以交换,也就是后面一个,和后面两个结点都不是null的情况,才可以。同时写的顺序也不能反,否则会报null.next的错误

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode swapPairs(ListNode head) {ListNode dummyNode = new ListNode(-1);dummyNode.next = head;ListNode pre = dummyNode;while(pre.next != null && pre.next.next != null){// ListNode tmp = pre.next.next;// pre.next.next = tmp.next;// tmp.next = pre.next;// pre.next = tmp;// pre = pre.next.next;ListNode firstNode = pre.next;ListNode secondNode = pre.next.next;firstNode.next = secondNode.next;secondNode.next = pre.next;pre.next = secondNode;pre = pre.next.next;}return dummyNode.next;}
}

时间复杂度 O(n)

19. 删除链表的倒数第 N 个结点

题目连接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。尝试用一遍扫描实现。

解法:快慢指针

让快指针先移动n步,然后这样再同时移动。
此时快指针移动了size-n步,慢指针也是size-n步,此时慢指针离最后距离也是size-(size-n)=n,也就是题意。
写过一次,有思路就很快了。

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyNode = new ListNode(-1);dummyNode.next = head;// 快慢双指针ListNode slow=dummyNode,fast=dummyNode;// 快指针先移动n步for(int i=0;i<n;i++){fast = fast.next;}// 然后这个时候,快指针和慢指针,再同时移动。直到快指针移动到最后while(fast.next!=null){fast = fast.next;slow = slow.next;}// 此时的slow指针指向的是要删除的结点的前一个slow.next = slow.next.next;return dummyNode.next;}
}

时间复杂度O(n)

面试题 02.07. 链表相交

题目连接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

解法:求两个链表交点节点的指针

特别注意!!! 交点不是数值相等,而是指针相等。不用比较val,只要比较两个指针是否相等,即可
还有个地方,两个链表的末端一定要先对齐,要不然不满足题意。也就是说,两个链表的指针起始位置是不一样的。一个是在开始处,一个不是。
在这里插入图片描述

/**
/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 先求两个链表的长度int lenA = 0, lenB = 0;ListNode curA = headA,curB = headB;while(curA!= null){curA = curA.next;++lenA;}while(curB!=null){curB = curB.next;++lenB;}curA = headA;curB = headB;// 把A确定为更长的if(lenA<lenB){// 交换结点ListNode tmp = curB;curB = curA;curA = tmp;int tmpLen = lenB;lenB = lenA;lenA = tmpLen;}// 对齐末端int gap = lenA-lenB;while(gap-- >0){curA = curA.next;}// 然后这个时候再比较指针是否相同,不是比较val是否相同while(lenB-- >0){if(curA==curB){return curA;}curA = curA.next;curB = curB.next;}return null;}
}

时间复杂度:O(n)

142.环形链表II

题目连接:https://leetcode.cn/problems/linked-list-cycle-ii/

解法1:快慢指针法

主要考察两知识点:
(1)判断链表是否环
(2)如果有环,如何找到这个环的入口

判断链表是否有环

可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。

如果有环,如何找到这个环的入口

假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:
在这里插入图片描述
slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。
(slow指针肯定是走了一圈不到的,因为他俩的速度差在一圈内是完全追的上的)

因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:

(x + y) * 2 = x + y + n (y + z)

两边消掉一个(x+y): x + y = n (y + z)

因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。

所以要求x ,将x单独放在左面:x = n (y + z) - y ,

再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z 注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针。

这个公式说明什么呢?

先拿n为1的情况来举例,意味着fast指针在环形里转了一圈之后,就遇到了 slow指针了。

当 n为1的时候,公式就化解为 x = z,

这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。

也就是在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。

让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。

/*** Definition for singly-linked list.* class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public ListNode detectCycle(ListNode head) {// 方法2:快慢指针ListNode slowIndex = head,fastIndex = head;while(fastIndex!=null && fastIndex.next != null){// 快指针一次移动两格,慢指针一次移动一格fastIndex = fastIndex.next.next;slowIndex = slowIndex.next;// 有环的情况if(slowIndex == fastIndex){// 相交的点ListNode joint = slowIndex;ListNode startNode = head;// 需要数学证明!// 从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点, // 那么当这两个指针相遇的时候就是 环形入口的节点。while(startNode!=joint){joint = joint.next;startNode = startNode.next;}return joint;}}return null;}
}

时间复杂度:O(n)
空间复杂度:O(1)

解法2:哈希法

一种非常直观的解法,我们遍历链表中的每个节点,并将它记录下来;一旦遇到了此前遍历过的节点,就可以判定链表中存在环。借助哈希表可以很方便地实现。

/*** Definition for singly-linked list.* class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public ListNode detectCycle(ListNode head) {// 方法1:哈希表的方式ListNode cur = head;HashSet<ListNode>nodes = new HashSet<ListNode>();while(cur!=null){if(nodes.contains(cur))return cur;elsenodes.add(cur);cur = cur.next;}return null;}
}

时间复杂度:O(n)
空间复杂度:O(n),n为链表中节点的数目

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

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

相关文章

Centos7编译Python3.11源码并安装完成的详细教程

Python3.11的Linux源码&#xff1a; Index of /ftp/python/https://www.python.org/ftp/python/由于Centos7里自带的openssl是1.0版本的&#xff0c;而Centos Stream8和9用的是openssl-1.1.1版本的。 注意&#xff1a;openssl必须是openssl-1.1.1版本的&#xff0c;虽然最高版…

QT的事件机制

QT的事件机制 文章目录 QT的事件机制 1、QT的事件机制。2、QT事件的整体流程。1、事件处理函数。1、鼠标按下与鼠标释放事件。2、事件的接收与忽略(accept()和ignore()函数&#xff09;。 2.事件的分发enevt()1、事件分发的dome。2、enevt事件的缺点。 3、事件的过滤器。 3、总…

通过本质看现象:关于Integer受内部初始化赋值范围限制而出现的有趣现象

文/朱季谦 这是我很多年前的第一篇技术博客&#xff0c;当时作为一名技术小菜鸟&#xff0c;总体而言显得很拙见&#xff0c;但也算是成长路上的一个小脚印&#xff0c;希望能在以后的日子里&#xff0c;可以对JAVA技术有一个更加深入的思考与认识。 前几天我在逛论坛的时候&a…

SSM基础入门

SSM Mybatis、Spring和SpringMVC这三个框架整合在一起完成业务功能开发 文章目录 SSM5.1 流程5.2 详细步骤5.2.1 基本配置5.2.2 功能模块开发5.2.3 测试5.2.3.1 单元测试5.2.3.2 PostMan测试 5.3 统一结果封装5.3.1 概念5.3.2 实现 5.4 统一异常处理5.4.1 异常处理器的使用5.4…

Linux Centos7静默安装(非图形安装)Oracle RAC 11gR2(Oracle RAC 11.2.0.4)

Oracle RAC (全称Oracle Real Application Clusters &#xff09;静默安装&#xff08;非图形安装&#xff09;教程。 由于这篇文章花费了我太多时间&#xff0c;设置了仅粉丝可见&#xff0c;见谅。 环境说明&#xff1a; 虚拟机软件&#xff1a;VMware Workstation 16 Pro…

Git与VScode联合使用详解

目录 Git与VScode联合使用 方式一 1. 用vscode打开文件夹&#xff0c;如图点击初始化仓库&#xff0c;把此仓库初始为git仓库。 2. 提交文件到本地仓库 3. vscode与github账号绑定 4. 在github中建立远程仓库 5. 本地仓库与远程仓库绑定 方式二 1. 在github上建立远程仓…

VSCode添加Python解释器并安装Python库

目录 一、安装VSCode 二、安装Python解释器 1、安装包链接 2、安装过程 3、测试 4、安装flake8和yapf两个包 &#xff08;1&#xff09;安装flake8包 &#xff08;2&#xff09;安装yapf包 三、VSCode中选择python解释器 一、安装VSCode VSCode安装教程&#xff08;默…

Windows之任意文件删除到提权

前言 ZDI 发表过从任意文件夹删除到提权的利用过程&#xff0c;还提供了任意文件删除到提权的利用过程&#xff0c;所以一字之差但是漏洞利用方式也是有细微偏差的。 这里把任意文件删除和任意文件夹删除漏洞提权结合起来分析&#xff0c;是因为其最后的利用过程是一样的&…

认识监控系统zabbix

利用一个优秀的监控软件&#xff0c;我们可以: ●通过一个友好的界面进行浏览整个网站所有的服务器状态 ●可以在 Web 前端方便的查看监控数据 ●可以回溯寻找事故发生时系统的问题和报警情况 了解zabbix zabbix是什么&#xff1f; ●zabbix 是一个基于 Web 界面的提供分布…

JVM:从零到入门

JVM&#xff0c;就是Java虚拟机。 JVM是一个巨大的话题&#xff0c;我们本文主要简单介绍一些围绕JVM相关的基础知识。 目录 JVM内存区域划分 本地方法栈 虚拟机栈 堆 程序计数器 方法区/ 元数据区 类加载 1.加载 2.验证 3.准备 4.解析 5.初始化 双亲委派模型 …

yydict属性字典-一种更加方便的方式访问字典

yydict属性字典-一种更加方便的方式访问字典 问题引入 这篇文章是想介绍 最近在使用字典的一种困惑. 我希望通过少写几个字符来访问 python中字典这种数据结构. 比如这个例子: person {name: frank,age: 18,hobby: swimming }在python中字典的定义 如上面的例子, 如果我希…

spring boot mybatis plus mapper如何自动注册到spring bean容器

##Import(AutoConfiguredMapperScannerRegistrar.class) ##注册MapperScannerConfigurer ##MapperScannerConfigurer.postProcessBeanDefinitionRegistry方法扫描注册mapper ##找到mapper候选者 ##过滤mapper 类 候选者 ##BeanDefinitionHolder注册到spring 容器

vue项目之.env文件.env.dev、test、pro

.env文件是vue运行项目时的环境配置文件。 .env: 全局默认配置文件&#xff0c;所有环境(开发、测试、生产等&#xff09;均会加载并合并该文件 .env.development(开发环境默认命名) 开发环境的配置&#xff0c;文件名默认为.env.development,如果需要改名也是可以的&#xf…

【Python】使用pyinstaller打包为Windows平台的xxx.exe方法步骤

pyinstaller 是一个用于将 Python 代码打包成独立可执行文件的工具&#xff0c;它可以将 Python 代码打包成 Windows、Linux、Mac 等平台的可执行文件&#xff0c;方便用户在不同环境中运行。 pyinstaller用法&#xff1a; 1.安装pyinstaller库&#xff0c;这里以PyCharm环境为…

ACM论文LaTeX模板解析(一)| 模板下载与安装

本文收录于专栏&#xff1a;ACM 论文 LaTeX模板解析&#xff0c;本专栏将会围绕ACM 论文 LaTeX模板解析持续更新。欢迎点赞收藏关注&#xff01; 文章目录 1. 引言2. 下载方式 1. 引言 计算机械协会&#xff08;ACM&#xff0c;Association for Computing Machinery&#xff0…

UG装配-WAVE几何链接器

自上向下&#xff08;自顶向下&#xff09;设计 先将产品主要结构&#xff08;或主要部件&#xff09;建立好&#xff0c;然后再根据要求设计其它组件&#xff0c;使每个组件之间有数据关联&#xff0c;适用于产品开发初期&#xff0c;便于修改&#xff0c;修改组件数据后&…

基于JavaWeb的酒店管理系统

基于JavaWeb的酒店管理系统 文章目录 基于JavaWeb的酒店管理系统系统介绍技术选型成果展示源码获取账号地址及其他说明 系统介绍 基于JavaWeb的酒店管理系统是为酒店打造的管理平台&#xff0c;其主要功能有管理员登陆、客房预订、客房入住、房间管理、数据查询(预订单查询、入…

PySide6/PyQt6中的时间管理类:QTime的使用方法

文章目录 📖 介绍 📖🏡 环境 🏡📒 使用方法 📒📝 创建QTime对象📝 常用方法⚓️ 相关链接 ⚓️📖 介绍 📖 QTime是PySide6中用于处理时间段的类,可以用来表示一天中的时间,例如小时、分钟和秒。它提供了许多操作和格式化时间的功能,使得处理时间变得更加…

mysql-实战案例 (超详细版)

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…

VL53L4CD TOF开发(1)----驱动TOF进行测距

VL53L4CX TOF开发.1--驱动TOF进行测距 概述视频教学样品申请完整代码下载主要特点硬件准备技术规格系统框图应用示意图生成STM32CUBEMX选择MCU串口配置IIC配置 XSHUTX-CUBE-TOF1演示结果 概述 VL53L4CD适用于接近测量和短距离测量&#xff0c;可实现从仅仅1 mm到1300 mm的超精…