目录

前言

一、链表的回文结构

二、相交链表

三、环形链表​编辑

四、环形链表II

总结


前言

        本篇博客将继续介绍单链表相关的算法题,包括了链表的回文结构、相交链表、环形链表等。现在就让我们正式开始吧!


一、链表的回文结构

        题目链接:链表的回文结构_牛客题霸_牛客网

        思路:创建数组(大小为900),遍历链表将节点的值依次存储在数组中,若数组为回文结构,则链表为回文结构。

        解题核心逻辑如下:

  1. 将链表值复制到数组:遍历链表,将所有节点的值存储到数组中;

  2. 使用双指针判断回文:从数组两端向中间遍历,比较对应位置的值是否相等;

  3. 返回判断结果:如果所有对应位置都相等,则是回文;否则不是。

        完整代码如下所示:

class PalindromeList {
public:bool chkPalindrome(ListNode* A) {// 创建固定大小的数组int arr[900] = {0};  // 假设链表长度不超过900// 遍历链表,将值存储到数组中ListNode* pcur = A;int i = 0;while(pcur) {arr[i++] = pcur->val;  // 存储当前节点值,i后移pcur = pcur->next;     // 移动到下一个节点}// 使用双指针判断数组是否为回文int left = 0, right = i - 1;  // i是链表长度while(left < right) {if(arr[left] != arr[right]) {return false;  // 发现不对称,不是回文}left++;right--;}return true;  // 所有对应位置都相等,是回文}
};

        代码的执行流程示例如下:假设链表为1 → 2 → 3 → 2 → 1 → NULL

步骤1:复制到数组
遍历链表:arr[0]=1, arr[1]=2, arr[2]=3, arr[3]=2, arr[4]=1
i=5(链表长度)步骤2:双指针判断
left=0, right=4: 1==1 ✓
left=1, right=3: 2==2 ✓  
left=2, right=2: 循环结束
返回true

二、相交链表

        题目链接:160. 相交链表 - 力扣(LeetCode)

        思路:求两个链表的长度,长链表先走长度差步,短链表开始同步遍历,找相同的结点。

        解题核心逻辑如下:

  1. 计算链表长度:分别遍历两个链表,计算它们的长度;

  2. 计算长度差:求出两个链表长度的差值;

  3. 对齐起点:让较长的链表先移动长度差的步数;

  4. 同时遍历:两个指针同时移动,直到找到相同节点或到达末尾。

        完整代码如下:

typedef struct ListNode ListNode;struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {// 求链表的长度ListNode* pa = headA;ListNode* pb = headB;int sizeA = 0, sizeB = 0;// 计算链表A的长度while(pa) {++sizeA;pa = pa->next;}// 计算链表B的长度while(pb) {++sizeB;pb = pb->next;}// 求长度差int gap = abs(sizeA - sizeB);  // 求绝对值// 定义长短链表ListNode* shortList = headA;ListNode* longList = headB;// 确定哪个链表更长if(sizeA > sizeB) {longList = headA;shortList = headB;}// 长链表先走gap步,对齐起点while(gap--) {longList = longList->next;}// shortList和longList现在在同一起跑线while(shortList) {  // 或者用while(longList)if(shortList == longList) {  // 找到相交节点return shortList;}shortList = shortList->next;longList = longList->next;}// 链表不相交return NULL;
}

        执行流程的示例如下:

        假设:
        链表A:1 → 2 → 3 → 4 → 5 → NULL(长度5)
        链表B:9 → 8 → 4 → 5 → NULL(长度4,从节点4开始相交)

步骤1:计算长度
sizeA = 5, sizeB = 4步骤2:计算长度差
gap = |5-4| = 1步骤3:确定长短链表
longList = headA, shortList = headB步骤4:长链表先走1步
longList从节点1移动到节点2步骤5:同时遍历
shortList=9, longList=2 → 不相等
shortList=8, longList=3 → 不相等  
shortList=4, longList=4 → 相等,返回节点4

三、环形链表

        题目链接:141. 环形链表 - 力扣(LeetCode)

        思路:采用快慢指针方法,慢指针每次走一步,快指针每次走两步,如果slow和fast指向了同一个结点,说明链表带环。

        对于这个思路,我们可以尝试证明一下:

        证明1:在环形链表中,慢指针每次走一步,快指针每次走两步,最终是否一定会相遇?

        如上图所示,假设此时slow刚入环,此时slow和fast之间的距离最大,为N。slow和fast各自移动一次之后,距离缩小2 - 1 = 1,则此时距离为N - 1,那么在移动N次之后,最后fast和slow之间的距离将缩短为0,两指针相遇。

        证明2:在环形链表中,慢指针每次走一步,快指针每次走3、4、5、……步,快慢指针在环形链表中还会相遇吗?答案是一定会相遇。

        如上图,假设此时slow刚入环,此时slow和fast之间的距离最大,为N。慢指针每次走一步,快指针每次走三步。每走一次,slow和fast之间距离就减小2,此时若N为偶数,那么最后两者距离将减小为0,相遇;若N为奇数,那么距离会缩小为-1,此时就会套圈,两者此时距离须以C-1来计算。若C-1为偶数,即C为奇数,那么一定会相遇;如果C-1为奇数,即C为偶数,则一定不会相遇。

        下面我们再来推导一下快慢指针走的路程之间的关系:

        如上图,我们假设慢指针每次走1步,快指针一次走3步,那么就有:3 * 慢指针 = 快指针。我们假设慢指针所走路程为L,则快指针所走路程为:L + C - N + nC。根据以上等式,就有:3L = L + C - N + nC,整理得到:2L = (n+1)C - N。如下:

💡TIPS

        虽然我们已经证明了快指针无论走多少步都可以满足在带环链表中相遇,但是在编写代码的时候会有额外的步骤引入,涉及到快慢指针的算法题中通常习惯使用慢指针走一步快指针走两步的方式。

        因此本题我们解题的核心逻辑如下:

       1.  初始化两个指针

        slow(慢指针):每次移动一步;

        fast(快指针):每次移动两步。

        2.  同时移动指针

                慢指针每次移动1步,快指针每次移动2步;

                如果链表有环,快慢指针最终会相遇;

                如果链表无环,快指针会先到达NULL。

        3.  终止条件

                快慢指针相遇 → 有环,返回true;

                快指针到达NULL → 无环,返回false。

        完整代码如下:

typedef struct ListNode ListNode;bool hasCycle(struct ListNode *head) {// 创建快慢指针ListNode* slow = head;  // 慢指针,每次移动1步ListNode* fast = head;  // 快指针,每次移动2步// 循环条件:快指针和快指针的下一个节点都不为NULLwhile(fast && fast->next) {slow = slow->next;        // 慢指针移动1步fast = fast->next->next;  // 快指针移动2步if(slow == fast) {        // 如果相遇return true;          // 链表有环}}// 快指针到达NULL,链表不带环return false;
}

        下面提供两个执行流程的示例:

        1.  有环链表:1 → 2 → 3 → 4 → 5 → 3(形成环)

初始:slow=1, fast=1
第1轮:slow=2, fast=3
第2轮:slow=3, fast=5  
第3轮:slow=4, fast=3
第4轮:slow=5, fast=5 → 相遇,返回true初始:slow=1, fast=1
第1轮:slow=2, fast=3
第2轮:slow=3, fast=5  
第3轮:slow=4, fast=3
第4轮:slow=5, fast=5 → 相遇,返回true

        2.  无环链表: 1→ 2 → 3 → 4 → 5 → NULL

初始:slow=1, fast=1
第1轮:slow=2, fast=3
第2轮:slow=3, fast=5
第3轮:slow=4, fast=NULL → 循环结束,返回false

四、环形链表II

        题目链接:142. 环形链表 II - 力扣(LeetCode)

        思路:快慢指针,在环里一定会相遇。相遇点到入环结点的距离 == 头结点到入环结点的距离

💡结论

        让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。

        下面我们先来证明一下以上结论:

        H为链表的起始点,E为环的入口点,M与判环时候相遇点。

        假设:环的长度为R,H到E的距离为L,E到M的距离为X,则:M到E的距离为R - X。

        在判环的时候,快慢指针相遇时所走的路径长度如下:

  • fast:L + X + nR
  • slow:L + X 

        需要注意的是:

        1.  当慢指针进入环时,快指针可能已经在环中绕了n圈了,n至少为1。因为当快指针先进环走到M的位置,最后又会在M的位置与慢指针相遇。

        2.  慢指针进入环之后,快指针肯定会在慢指针走一圈之内追上慢指针。因为当慢指针进环之后,快慢指针之间的距离最多就是环的长度,而两个指针在移动的时候,每次它们的距离都缩减一步,因此在慢指针移动一圈之前,快指针肯定是可以追上慢指针的,而快指针的速度是慢指针的两倍,因此有如下关系:

        2 * (L + X) = L + X + nR;

        L + X = nR;

        L = nR - X;

        L = (n - 1)R + (R - X)

        (n = 1、2、3、4、……、n,n的大小取决于环的大小,环越小n越大)

        在极端情况下,我们假设n = 1,此时有:L = R - X。

        即:一个指针从链表起始位置运行,一个指针从相遇点位置绕环,每次都走一步,两个指针最终会在入口点的位置相遇。

        完整代码如下:

typedef struct ListNode ListNode;struct ListNode *detectCycle(struct ListNode *head) {// 创建快慢指针ListNode* slow = head;  // 慢指针,每次移动1步ListNode* fast = head;  // 快指针,每次移动2步// 第一阶段:判断是否有环while(fast && fast->next) {slow = slow->next;        // 慢指针移动1步fast = fast->next->next;  // 快指针移动2步if(slow == fast) {        // 如果相遇,说明有环// 第二阶段:寻找环入口// 数学原理:头节点到入口的距离 = 相遇点到入口的距离ListNode* pcur = head;while(pcur != slow) {pcur = pcur->next;  // pcur从头节点开始slow = slow->next;  // slow从相遇点开始}return pcur;  // 相遇点即为环入口}}// 快指针到达NULL,链表不带环return NULL;
}

        执行流程示例如下:1 → 2 → 3 → 4 → 5 → 3(形成环,入口在节点3)

步骤1:判断有环
slow=1, fast=1
slow=2, fast=3
slow=3, fast=5  
slow=4, fast=3
slow=5, fast=5 → 相遇在节点5

步骤2:寻找环入口
pcur=head=1, slow=5
pcur=2, slow=3
pcur=3, slow=3 → 相遇在节点3(环入口)
返回节点3


总结

        以上就是本期单链表算法题的全部内容啦~~~下期博客我将为大家带来双向链表的相关知识介绍,请大家多多关注、多多支持哦!

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

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

相关文章

【AI自动化】VSCode+Playwright+codegen+nodejs自动化脚本生成

VSCodePlaywrightnodejs&#xff0c;能完美实现UI自动化全流程脚本自动生成和回放&#xff0c;生成的脚本方便维护&#xff0c;回放执行快速&#xff1b; 概述 Playwright 是由Microsoft开发的一个开源的跨浏览器自动化测试库&#xff0c;它支持Chromium、WebKit和Firefox浏览…

基于能量方法的纳维-斯托克斯方程高阶范数有界性理论推导-陈墨仙

写在最前面&#xff0c;圈外人&#xff0c;没有背书没有教育邮箱&#xff0c;发不了预印本&#xff0c;我先发csdn。刚才首发没复制完&#xff0c;抱歉&#xff0c;现在编辑下。基于能量方法的纳维-斯托克斯方程高阶范数有界性理论推导作者 陈墨仙邮件 2488888241qq.com摘要纳维…

Labview邪修01:贪吃蛇

从博主很小的时候就在掌机上玩过这个贪吃蛇的小游戏&#xff0c;突然有一天心血来潮的想Labview是不是也可以编这个小游戏&#xff0c;回忆一下童年&#xff01;然后就又了下面的这个程序&#xff0c;执行结果如下图所示。 基本功能&#xff1a; 1&#xff09;点击开始按钮&am…

将自己的jar包发布到maven中央仓库(2025-08-29)

将自己的jar包发布到maven中央仓库(2025-08-29) 一、注册账号 https://central.sonatype.com/ 二、新建命名空间 这里的命名空间需要填写github的用户名因为我的用户名是daimao0,所以命名空间填io.github.daimao0 这里要求你建一个名为ubuxfc5q7r的公共项目&#xff0c;先创…

Spring CompositeCacheManager融合缓存

这是一个非常实用但容易被忽视的组件,它在特定的缓存场景下能提供极大的灵活性。 1. 核心概念:它是什么? ​​CompositeCacheManager​​ 是 Spring Framework 缓存抽象(spring-context模块)的一部分。它的核心作用正如其名——​​组合(Composite)​​。 它本身并不…

无懈可击的 TCP AIMD

不特指 TCP AIMD&#xff0c;而泛指控制范畴的所有 Additive Increase / Multiplicative Decrease 算法&#xff0c;继 难以超越的 TCP AIMD 再叙。 “你永远不能仅凭 BBR 的吞吐更高就说 BBR 比 CUBIC 更好” 这句话怎么总是没人看&#xff0c;这句话是这一系列文章的前提论点…

数据集数量与神经网络参数关系分析

1. 理论基础 1.1 经验法则与理论依据 神经网络的参数量与所需数据集大小之间存在重要的关系&#xff0c;这直接影响模型的泛化能力和训练效果。 经典经验法则10倍法则&#xff1a;数据样本数量应至少为模型参数量的10倍 公式&#xff1a;数据量 ≥ 10 参数量适用于大多数监督学…

项目经验处理

订单取消和支付成功并发问题 这是一个非常经典且重要的分布式系统问题。订单取消和支付成功同时发生&#xff0c;本质上是一个资源竞争问题&#xff0c;核心在于如何保证两个并发操作对订单状态的修改满足业务的最终一致性&#xff08;即一个订单最终只能有一种确定的状态&…

rabbitmq学习笔记 ----- 多级消息延迟始终为 20s 问题排查

问题现象 在实现多级延迟消息功能时&#xff0c;发现每次消息延迟间隔始终为20s&#xff0c;无法按照预期依次使用20s→10s→5s的延迟时间。日志显示每次处理时移除的延迟时间都是20000L。 问题代码片段 1.生产者 Testvoid sendDelayMessage2() {List<Long> expireTimeLi…

软件测试(三):测试流程及测试用例

1.测试流程1.需求分析进行测试之前先阅读需求文档&#xff0c;分析指出不合理或不明确的地方2.计划编写与测试用例测试用例用例即&#xff1a;用户使用的案例测试用例&#xff1a;执行测试的文档作用&#xff1a;用例格式&#xff1a;----------------------------------------…

Python:列表的进阶技巧

列表&#xff08;list&#xff09;作为 Python 最常用的数据结构之一&#xff0c;不仅能存储有序数据&#xff0c;还能在推导式、函数参数传递、数据处理等场景中发挥强大作用。下面介绍一些进阶技巧与常见应用。一、去重与排序1、快速去重&#xff08;不保序&#xff09;nums …

【完整源码+数据集+部署教程】硬币分类与识别系统源码和数据集:改进yolo11-SWC

背景意义 随着经济的发展和数字支付的普及&#xff0c;传统硬币的使用逐渐减少&#xff0c;但在某些地区和特定场合&#xff0c;硬币仍然是重要的支付手段。因此&#xff0c;硬币的分类与识别在自动化支付、智能零售和物联网等领域具有重要的应用价值。尤其是在银行、商超和自助…

莱特莱德:以“第四代极限分离技术”,赋能生物发酵产业升级

莱特莱德&#xff1a;以“第四代极限分离技术”&#xff0c;赋能生物发酵产业升级Empowering Upgrades in the Bio-Fermentation Industry with "Fourth-Generation Extreme Separation Technology生物发酵行业正经历从 “规模扩张” 向 “质效提升” 的关键转型&#xff…

外卖大战之后,再看美团的护城河

美团&#xff08;03690.HK&#xff09;于近日发布了2025年Q2财报&#xff0c;市场无疑将更多目光投向了其备受关注的外卖业务上。毫无悬念&#xff0c;受外卖竞争和加大投入的成本影响&#xff0c;美团在外卖业务上的财务数据受到明显压力&#xff0c;利润大幅下跌&#xff0c;…

R包fastWGCNA - 快速执行WGCNA分析和下游分析可视化

最新版本: 1.0.0可以对着视频教程学习和使用&#xff1a;然而还没录呢, 关注B站等我更新R包介绍 开发背景 WGCNA是转录组或芯片表达谱数据常用得分析, 可用来鉴定跟分组或表型相关得模块基因和核心基因但其步骤非常之多, 每次运行起来很是费劲, 但需要修改的参数并不多所以完全…

GitHub 热榜项目 - 日榜(2025-08-29)

GitHub 热榜项目 - 日榜(2025-08-29) 生成于&#xff1a;2025-08-29 统计摘要 共发现热门项目&#xff1a;11 个 榜单类型&#xff1a;日榜 本期热点趋势总结 本期GitHub热榜展现出三大技术趋势&#xff1a;1&#xff09;AI应用持续深化&#xff0c;ChatGPT等大模型系统提示…

【深度学习实战(58)】bash方式启动模型训练

export \PATHPYTHONPATH/workspace/mmlab/mmdetection/:/workspace/mmlab/mmsegmentation/:/workspace/mmlab/mmdeploy/:${env:PYTHONPATH} \CUDA_VISIBLE_DEVICES0 \DATA_ROOT_1/mnt/data/…/ \DATA_ROOT_2/mnt/data/…/ \DATA_ROOT_MASK/…/ \PATH_COMMON_PACKAGES_SO…sonoh…

【物联网】关于 GATT (Generic Attribute Profile)基本概念与三种操作(Read / Write / Notify)的理解

“BLE 读写”在这里具体指什么&#xff1f; 在你的系统里&#xff0c;树莓派是 BLE Central&#xff0c;Arduino 是 BLE Peripheral。 Central 和 Peripheral 通过 **GATT 特征&#xff08;Characteristic&#xff09;**交互&#xff1a;读&#xff08;Read&#xff09;&#x…

JavaSE丨集合框架入门(二):从 0 掌握 Set 集合

这节我们接着学习 Set 集合。一、Set 集合1.1 Set 概述java.util.Set 接口继承了 Collection 接口&#xff0c;是常用的一种集合类型。 相对于之前学习的List集合&#xff0c;Set集合特点如下&#xff1a;除了具有 Collection 集合的特点&#xff0c;还具有自己的一些特点&…

金属结构疲劳寿命预测与健康监测技术—— 融合能量法、红外热像技术与深度学习的前沿实践

理论基础与核心方法 疲劳经典理论及其瓶颈 1.1.疲劳失效的微观与宏观机理&#xff1a; 裂纹萌生、扩展与断裂的物理过程。 1.2.传统方法的回顾与评析。 1.3.引出核心问题&#xff1a;是否存在一个更具物理意义、能统一描述疲劳全过程&#xff08;萌生与扩展&#xff09;且试验量…