当前位置: 首页 > news >正文

算法 day4 【双指针、快慢指针、环形链表】链表下

⚡刷题计划day4继续,可以点个免费的赞哦~

下一期将会开启哈希表刷题专题,往期可看专栏,关注不迷路,

您的支持是我的最大动力🌹~

目录

⚡刷题计划day4继续,可以点个免费的赞哦~

下一期将会开启哈希表刷题专题,往期可看专栏,关注不迷路,

您的支持是我的最大动力🌹~

题目一:19. 删除链表的倒数第 N 个结点

法一:计算链表长度

法二:双指针

题目二:面试题 02.07. 链表相交

法一:双指针

法二:合并链表实现同步移动

题目三:142. 环形链表 II

法一:快慢指针法

1.判断链表是否有环

2.如果有环,如何找到环的入口

2.1 n==1

2.2 n>1

法二:哈希表


题目一:19. 删除链表的倒数第 N 个结点

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

(https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/)

法一:计算链表长度

常规思路:先遍历得到链表长度L,然后再次遍历到 L-n+1个结点,便是我们需要删除的结点;

这里我们还是使用虚拟头结点统一,于是从虚拟结点开始遍历L-n+1个结点,它的下一个结点便是我们要删除的结点,这样我们只需修改一次指针,就可完成删除操作。

如图辅助理解:

AC代码

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyHead = new ListNode();dummyHead.next=head;ListNode cur = dummyHead;int length = getLength(head);for (int i=1;i<length-n+1;i++){cur = cur.next;}if(cur.next!=null){//避免空指针cur.next = cur.next.next;//删除操作}return dummyHead.next;
​}public int getLength(ListNode head){int length = 0;while(head != null){length++;head=head.next;}return length;}
}

法二:双指针

主要思路:

要删除倒数第n个,我们可以使用双指针,这样不用去求长度;

保持一个相差n的区间,fast在前,slow在后。这样等fast走到链表末尾,slow对应的就是我们要删除的结点;

因为链表删除我们需要通过前一个结点,所以将相差区间设为n+1,可以结合图理解:

AC代码

class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyHead = new ListNode();dummyHead.next=head;ListNode fast = dummyHead;ListNode slow = dummyHead;
​// 只要快慢指针相差 n 个结点即可for (int i=1;i<=n+1;i++){fast = fast.next;}while (fast!=null){fast = fast.next;slow = slow.next;}
​if(slow.next!=null){slow.next = slow.next.next;}return dummyHead.next;}
}

题目二:面试题 02.07. 链表相交

leetcode:面试题 02.07. 链表相交

(https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/)

简单来说,就是求两个链表交点节点的指针。 这里要注意,交点不是数值相等,而是指针相等。

为了方便举例,假设节点元素数值相等,则节点指针相等。

看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:

我们求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB 末尾对齐的位置,如图

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。

否则循环退出返回空指针。

AC代码

法一:双指针

public class Solution {
​public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 初始化两个链表的当前节点ListNode cur1 = headA;ListNode cur2 = headB;// 初始化两个链表的长度int len1 = 0;int len2 = 0;
​// 求cur1长度while (cur1 != null) {len1++;cur1 = cur1.next;}// 求cur2长度while (cur2 != null) {len2++;cur2 = cur2.next;}
​// 重新初始化两个链表的当前节点cur1 = headA;cur2 = headB;
​// 如果第一个链表比第二个短,交换两个链表的头节点和长度if (len1 < len2) {//1. swap (len1, len2);int temp = len1;len1 = len2;len2 = temp;//2. swap (cur1, cur2);ListNode temNode = cur1;cur1 = cur2;cur2 = temNode;}
​// 计算长度的差值int gap = len1 - len2;// 移动较长链表的当前节点,使cur1与cur2的末尾位置对齐,看图while (gap-- > 0) {cur1 = cur1.next;}
​// 同时遍历两个链表,遇到相同则直接返回while (cur1 != null) {if (cur1 == cur2) {return cur1; // 返回相交的节点}cur1 = cur1.next;cur2 = cur2.next;}
​// 如果两个链表没有相交,返回nullreturn null;}
}

法二:合并链表实现同步移动

主要思路:

  1. 同步移动指针

    • 使用一个 while 循环,只要 p1p2 没有相遇,就继续移动指针。

    • 对于 p1,如果它到达了链表 A 的末尾(即 p1null),则将它移动到链表 B 的头部,重新开始遍历。

    • 对于 p2,如果它到达了链表 B 的末尾(即 p2null),则将它移动到链表 A 的头部,重新开始遍历。

  2. 相遇即相交

    • 当两个指针 p1p2 相遇时,它们指向的就是链表相交的节点。因为两个指针最终都会遍历完两个链表,如果链表有相交点,它们最终会在相交点相遇。

  3. 返回结果

    • 一旦 p1p2 相遇,即它们指向同一个节点,就返回这个节点。

 public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// p1 指向 A 链表头结点,p2 指向 B 链表头结点ListNode p1 = headA, p2 = headB;while (p1 != p2) {// p1 走一步,如果走到 A 链表末尾,转到 B 链表if (p1 == null) p1 = headB;else            p1 = p1.next;// p2 走一步,如果走到 B 链表末尾,转到 A 链表if (p2 == null) p2 = headA;else            p2 = p2.next;}return p1;}
}

题目三:142. 环形链表 II

leetcode:142. 环形链表 II

(https://leetcode.cn/problems/linked-list-cycle-ii/description/)

法一:快慢指针法

判断链表是否有环,我们一般可以使用快慢指针法

此题还是有一定难度,考察了对链表环的判断,已经需要进行数学运算,下文会进行详细解释。

对于此题大致分为两大步:

1.判断链表是否有环

2.如果有环,如何找到环的入口


1.判断链表是否有环

分别定义fast,slow指针,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

2.如果有环,如何找到环的入口

这步已经可以判断链表是否有环了,接下来是寻找环的入口,需要用到一点数学运算。

假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:

那么当相遇时:

slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。

加深理解注:

1.fast指针为什么 n (y + z)? 因为fast比slow快,fast进入圈后至少需要一圈后追反超slow,由此也可知道,n>=1(后续解题会用)。

2.为什么slow就不用比如k(y+z)? 因为slow进入圈后在一圈内一定会被fast追上

3.那为什么slow一圈内就一定会被fast追上呢? 可以这样通俗理解:首先fast会比slow快1,如果slow走一圈,fast就会走两圈,那一定会追上。

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

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

因为我们要找环形入口,即需要找x,将x单独放出来化简:

x = n (y + z) - y

但是我们看一下这个式子呢,也发现不了什么,我们是想通过右边的参数来求x,但发现目前右侧也没啥特殊形式,还有个-y。于是我们可以提一个(y+z)出来,

x = (n - 1) (y + z) + z(此处n>=1,前面有解释)

此时就明了了。


2.1 n==1

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

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

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

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

2.2 n>1

那么 n如果大于1是什么情况呢,就是fast指针在环形转n圈之后才遇到 slow指针。

其实这种情况和n为1的时候效果是一样的,一样可以通过这个方法找到 环形的入口节点,只不过,index1 指针在环里 多转了(n-1)圈,然后再遇到index2,相遇点依然是环形的入口节点。

代码如下:

public class Solution {public ListNode detectCycle(ListNode head) {ListNode fast = head;ListNode slow = head;while(fast!=null && fast.next!=null){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;}
}

法二:哈希表

这个思路就简单很多,时间复杂度:O(N),空间复杂度:O(N);

但第一种双指针的解法也需要掌握,时间复杂度:O(N),空间复杂度:O(1)。

关于哈希表我们下期也会做相应的专题刷题。

主要思路:遍历链表中的每个节点,并将它记录下来;一旦遇到了此前遍历过的节点,就可以判定链表中存在环。借助哈希表可以很方便地实现。

代码:

详细见注解

public class Solution {public ListNode detectCycle(ListNode head) {// 初始化指针pos指向头结点ListNode pos = head;// 使用HashSet来存储已经访问过的节点Set<ListNode> visited = new HashSet<ListNode>();
​// 遍历链表while (pos != null) {// 如果当前节点已经被访问过,说明存在环,返回当前节点if (visited.contains(pos)) {return pos;} else {// 否则,将当前节点添加到visited集合中visited.add(pos);}// 移动到下一个节点pos = pos.next;}
​// 如果遍历完整个链表都没有发现环,返回nullreturn null;}
}

相关文章:

算法 day4 【双指针、快慢指针、环形链表】链表下

⚡刷题计划day4继续&#xff0c;可以点个免费的赞哦~ 下一期将会开启哈希表刷题专题&#xff0c;往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的支持是我的最大动力&#x1f339;~ 目录 ⚡刷题计划day4继续&#xff0c;可以点个免费的赞哦~ 下一期将会开启哈希表刷题…...

智能音箱的工作原理

智能音箱的工作原理主要涉及到硬件和软件两个层面的协同工作&#xff0c;以及多个关键技术环节的配合。以下是对智能音箱工作原理的详细解析&#xff1a; 一、硬件层面 智能音箱的硬件组成通常包括主控芯片、麦克风阵列、扬声器、Wi-Fi模块和电源等部分。 主控芯片&#xff1…...

国际金融入门:国际收支与平衡表解析

在全球化的经济体系中&#xff0c;国际金融已成为我们日常生活不可或缺的一部分。了解国际金融的基础知识&#xff0c;可以帮助我们更好地理解世界经济的动态和趋势。今天&#xff0c;我们将深入探讨国际收支及其平衡表&#xff0c;以及它们是如何影响国家经济。 国际收支&…...

Modbus转BACnet/IP网关的技术实现与应用

引言 随着智能建筑和工业自动化的快速发展&#xff0c;不同通信协议之间的数据交换也变得日益重要。Modbus和BACnet/IP是两种广泛应用于自动化领域的通信协议&#xff0c;Modbus以其简单性和灵活性被广泛用于工业自动化&#xff0c;而BACnet/IP则在楼宇自动化系统中占据主导地…...

数据库连接断开后,DBAPI的数据源如何自动重连

现象 在使用DBAPI的过程中&#xff0c;如果网络抖动导致数据库连接不上&#xff0c;发现DBAPI的数据源不能重连&#xff0c;必须重启DBAPI才能连上数据库 解决办法 在数据源的连接池参数配置druid.breakAfterAcquireFailurefalse注意在企业版的4.1.1及以上版本才可以配置连接…...

Microsoft 365 Office BusinessPro LTSC 2024 for Mac( 微软Office办公套件)

Microsoft 365 Office BusinessPro LTSC 2024是一款专为商业用户设计的办公软件套件&#xff0c;它集成了Word、Excel、PowerPoint等核心应用&#xff0c;并特别包含了Microsoft Teams这一强大的协作工具。Teams将聊天、会议、文件共享、任务管理等功能整合到一个平台上&#x…...

svelte - 1. 基础知识

svelte中文官网 vue和svelt语法对比 掘金-svelte入门简介 文章目录 1、基本页面框架2、动态属性3、嵌套组件4、@html: 插入html标签,显示真实dom元素5、点击事件 on:click={handleClick}6、响应式声明7、父子组件通信8、if-else(1)if(2)if - else(3)if - else if - else…...

挖掘基于边缘无线协同感知的低功耗物联网 (LPIOT) 的巨大潜力

关键词&#xff1a;边缘无线协同感知、低功耗物联网(LPIOT)、无线混合组网、用电监测、用电计量、多角色、计量插座、无线场景感知、多角色运用、后台边缘层&#xff0c;网络边缘层&#xff0c;场景能效管理&#xff0c;场景能耗计算 在数字化和智能化日益加速的今天&#xff…...

iOS开发设计模式篇第一篇MVC设计模式

目录 1. 引言 2.概念 1.Model 1.职责 2.实现 3.和Controller通信 1.Contrller直接访问Model 2.通过委托(Delegate)模式 3.通知 4.KVO 4.设计的建议 2.View 1.职责 2.实现 3.和Controller通信 1. 目标-动作&#xff08;Target-Action&#xff09;模式 2…...

【React】全面解析:从基础知识到高级应用,掌握现代Web开发利器

文章目录 一、React 的基础知识1. 什么是 React&#xff1f;2. React 的基本概念3. 基本示例 二、React 的进阶概念1. 状态&#xff08;State&#xff09;和属性&#xff08;Props&#xff09;2. 生命周期方法&#xff08;Lifecycle Methods&#xff09;3. 钩子&#xff08;Hoo…...

神经网络之卷积神经网络

目录 一、卷积神经网络概述&#xff1a;1.卷积层&#xff1a;1.1卷积核与神经元&#xff1a;1.2卷积层作用&#xff1a;1.3多输出通道概念&#xff1a; 2.池化层&#xff1a;2.1池化层作用&#xff1a; 3.隐藏层与卷积层、池化层关系&#xff1a; 一、卷积神经网络概述&#xf…...

【Vue实战教程】之Vue工程化项目详解

Vue工程化项目 随着多年的发展&#xff0c;前端越来越模块化、组件化、工程化&#xff0c;这是前端发展的大趋势。webpack是目前用于构建前端工程化项目的主流工具之一&#xff0c;也正变得越来越重要。本章节我们来详细讲解一下如何使用webpack搭建Vue工程化项目。 1 使用we…...

DBeaver Ultimate 22.1.0 连接数据库(MySQL+Mongo+Clickhouse)

前言 继续书接上文 Docker Compose V2 安装常用数据库MySQLMongo&#xff0c;部署安装好之后我本来是找了一个web端的在线连接数据库的工具&#xff0c;但是使用过程中并不丝滑&#xff0c;最终还是选择了使用 DBeaver &#xff0c;然后发现 mongo 还需要许可&#xff0c;又折…...

探索PyMuPDF:Python中的强大PDF处理库

探索PyMuPDF&#xff1a;Python中的强大PDF处理库 背景&#xff1a;为何选择PyMuPDF 在数字化时代&#xff0c;PDF文件因其跨平台的兼容性和对格式的严格保持而成为文档交换的通用格式。然而&#xff0c;处理PDF文件往往需要专门的工具或库。这就是PyMuPDF库的用武之地。PyMuP…...

天润融通AI技术助力汽车行业销售革新,邀约到店率翻倍增长

2024年汽车行业增速放缓&#xff0c;市场竞争加剧。在这种背景下&#xff0c;人工智能的加速渗透&#xff0c;各大汽车厂商纷纷引入大模型技术&#xff0c;对传统营销方式进行升级改造&#xff0c;寻找新的增长空间。 一直以来&#xff0c;汽车厂商投入大量预算&#xff0c;对…...

ubuntu安装mysql8.0

文章目录 ubuntu版本安装修改密码取消root跳过密码验证 ubuntu版本 22.04 安装 更新软件包列表 sudo apt update安装 MySQL 8.0 服务器 sudo apt install mysql-server在安装过程中&#xff0c;系统可能会提示您设置 root 用户的密码&#xff0c;请务必牢记您设置的密码。…...

数字图像处理笔记(三) ---- 傅里叶变换的基本原理

系列文章目录 数字图像处理笔记&#xff08;一&#xff09;---- 图像数字化与显示 数字图像处理笔记&#xff08;二&#xff09;---- 像素加图像统计特征 数字图像处理笔记&#xff08;三) ---- 傅里叶变换的基本原理 文章目录 系列文章目录前言一、傅里叶变换二、离散傅里叶变…...

Golang | Leetcode Golang题解之第268题丢失的数字

题目&#xff1a; 题解&#xff1a; func missingNumber(nums []int) int {n : len(nums)total : n * (n 1) / 2arrSum : 0for _, num : range nums {arrSum num}return total - arrSum }...

Xlua原理 二

一已经介绍了初步的lua与C#通信的原理&#xff0c;和xlua的LuaEnv的初始化内容。 这边介绍下Wrap文件。 一.Wrap介绍 导入xlua后可以看到会多出上图菜单。 点击后生成一堆wrap文件&#xff0c;这些文件是lua调用C#时进行映射查找用的中间代码。这样就不需要去反射调用节约性…...

《数据结构》--顺序表

C语言语法基础到数据结构与算法&#xff0c;前面已经掌握并具备了扎实的C语言基础&#xff0c;为什么要学习数据结构课程&#xff1f;--我们学完本章就可以实践一个&#xff1a;通讯录项目 简单了解过后&#xff0c;通讯录具备增加、删除、修改、查找联系人等操作。要想实现通…...

日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻

在如今就业市场竞争日益激烈的背景下&#xff0c;越来越多的求职者将目光投向了日本及中日双语岗位。但是&#xff0c;一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧&#xff1f;面对生疏的日语交流环境&#xff0c;即便提前恶补了…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

UDP(Echoserver)

网络命令 Ping 命令 检测网络是否连通 使用方法: ping -c 次数 网址ping -c 3 www.baidu.comnetstat 命令 netstat 是一个用来查看网络状态的重要工具. 语法&#xff1a;netstat [选项] 功能&#xff1a;查看网络状态 常用选项&#xff1a; n 拒绝显示别名&#…...

测试markdown--肇兴

day1&#xff1a; 1、去程&#xff1a;7:04 --11:32高铁 高铁右转上售票大厅2楼&#xff0c;穿过候车厅下一楼&#xff0c;上大巴车 &#xffe5;10/人 **2、到达&#xff1a;**12点多到达寨子&#xff0c;买门票&#xff0c;美团/抖音&#xff1a;&#xffe5;78人 3、中饭&a…...

Bean 作用域有哪些?如何答出技术深度?

导语&#xff1a; Spring 面试绕不开 Bean 的作用域问题&#xff0c;这是面试官考察候选人对 Spring 框架理解深度的常见方式。本文将围绕“Spring 中的 Bean 作用域”展开&#xff0c;结合典型面试题及实战场景&#xff0c;帮你厘清重点&#xff0c;打破模板式回答&#xff0c…...

协议转换利器,profinet转ethercat网关的两大派系,各有千秋

随着工业以太网的发展&#xff0c;其高效、便捷、协议开放、易于冗余等诸多优点&#xff0c;被越来越多的工业现场所采用。西门子SIMATIC S7-1200/1500系列PLC集成有Profinet接口&#xff0c;具有实时性、开放性&#xff0c;使用TCP/IP和IT标准&#xff0c;符合基于工业以太网的…...

用鸿蒙HarmonyOS5实现中国象棋小游戏的过程

下面是一个基于鸿蒙OS (HarmonyOS) 的中国象棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。 1. 项目结构 /src/main/java/com/example/chinesechess/├── MainAbilitySlice.java // 主界面逻辑├── ChessView.java // 游戏视图和逻辑├──…...

API网关Kong的鉴权与限流:高并发场景下的核心实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 引言 在微服务架构中&#xff0c;API网关承担着流量调度、安全防护和协议转换的核心职责。作为云原生时代的代表性网关&#xff0c;Kong凭借其插件化架构…...

Ubuntu系统多网卡多相机IP设置方法

目录 1、硬件情况 2、如何设置网卡和相机IP 2.1 万兆网卡连接交换机&#xff0c;交换机再连相机 2.1.1 网卡设置 2.1.2 相机设置 2.3 万兆网卡直连相机 1、硬件情况 2个网卡n个相机 电脑系统信息&#xff0c;系统版本&#xff1a;Ubuntu22.04.5 LTS&#xff1b;内核版本…...

《Docker》架构

文章目录 架构模式单机架构应用数据分离架构应用服务器集群架构读写分离/主从分离架构冷热分离架构垂直分库架构微服务架构容器编排架构什么是容器&#xff0c;docker&#xff0c;镜像&#xff0c;k8s 架构模式 单机架构 单机架构其实就是应用服务器和单机服务器都部署在同一…...