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

hot100 回文链表(234)

本算法采用快慢指针定位、局部链表反转与双指针线性比对的组合方案解决“回文链表”判定问题。其核心本质是在不开辟额外存储空间的前提下,通过修改原链表后半段的拓扑结构实现前后数据的空间对齐。当前提供的源码实现了时间复杂度 O(n) 和额外空间复杂度 O(1) 的最优资源配置方案,最终走向是通过同步比对两个子链表的节点数值输出布尔判定结果。

一、 问题本质与数学模型

对于长度为 n 的单链表,若其满足回文特性,则链表从前向后遍历的节点数值序列与从后向前遍历的节点数值序列完全一致。

链表的物理结构只支持单向单驱寻址(next指针),无法直接进行双向逆序比对。为了在常数阶空间内完成判定,必须将链表在逻辑上切分为两个子链表:

  • 前半段链表:从原始头节点head开始,包含前 ⌊n/2⌋ 个节点。

  • 后半段链表:从中间节点开始直到尾节点,并将其拓扑结构完全反转,形成以反转后的尾节点为新头节点head2的逆序子链表。

比对两段子链表的数值序列,若在head2遍历至null期间所有对应节点的val全部相等,则该链表在数学上确立为回文链表。

二、 算法演进对比

在解决单链表回文验证问题时,各解法的资源消耗特征如下:

解法名称时间复杂度空间复杂度核心原理物理缺陷 / 瓶颈
辅助数组/列表法O(n)O(n)将链表所有节点数值复制到动态数组中,利用双指针向中间靠拢比对数值引入了与链表节点总数成正比的额外内存开销,非原地算法
链表完全克隆反转O(n)O(n)复制一份完全相同的链表并将其整体反转,随后同步比对原链表与新链表需要完整的二次节点内存分配
栈结构逆序比对O(n)O(n)将链表全量节点压入栈中,随后出栈与原链表节点进行比对栈帧或数据存储引发线性空间损耗
快慢指针+局部反转(当前解法)O(n)O(1)用快慢指针锁定中点,原地反转后半段链表并进行线性比对改变了原链表的后半段物理结构,若需恢复原状需二次反转

三、 核心控制逻辑拆解

该算法由三个独立的、互不嵌套的模块组合而成:

1. 快慢指针定位中点(mid函数)

  • 变量职责fast指针每步前进 2 个节点(fast.next.next),slow指针每步前进 1 个节点(slow.next)。

  • 运行机制:当fast触及链表末尾(null或尾节点)时,slow指针恰好停留在链表的几何中点位置(对于奇数长度,停留在正中节点;对于偶数长度,停留在后半段的首个节点)。该函数返回slow处的节点地址作为后半段链表的起点。

2. 原地链表反转(reverse函数)

  • 运行机制:利用cur,pre,nxt三个局部指针,单次线性扫描后半段链表,逐位逆转next指针的指向,最后返回逆序链表的新头节点地址pre

3. 同步双指针比对(isPalindrome主逻辑)

  • 控制条件while (head2 != null)。因为后半段链表的长度必然小于或等于前半段链表的长度,所以以head2释放作为判定终止信号。

  • 判定机制:每轮循环检测head2.val != head.val。若成立则直接终止流程并返回false;若相等则两个指针同时后移。

四、 算法执行状态机步进示例

以输入数据head = [1, 2, 2, 1]为例(长度 n=4),内部各模块执行时的变量状态演进如下表所示:

阶段 / 步骤当前控制变量状态作用的目标物理区间链表内部实时拓扑或状态值动作与结论
中点定位阶段初始:fast=head(1),slow=head(1)全局链表1 -> 2 -> 2 -> 1 -> null-
中点定位步进 1

fast推进至第三个节点2

slow推进至第二个节点2

全局链表1 -> 2 -> 2 -> 1 -> nullfast != null && fast.next != null成立,继续推进
中点定位步进 2

fast推进至null

slow推进至第三个节点2

全局链表1 -> 2 -> 2 -> 1 -> null循环终止,返回slow对应的子链表[2, 1]
局部反转阶段输入head2 = [2, 1],执行反转后半段链表区间反转后结构变为:1 -> 2 -> null返回新头节点地址,指向数值为 1 的节点
比对第 1 步

head指向第一个节点1

head2指向反转后新头节点1

两个子链表的首位1 == 1成立条件满足,headhead2同时后移一位
比对第 2 步

head指向第二个节点2

head2指向反转后第二个节点2

两个子链表的第二位2 == 2成立条件满足,headhead2同时后移一位
终止判定head2变为null比对结束-while循环破裂,未触发不相等分支,最终输出true

五、源码实现

/** * 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 boolean isPalindrome(ListNode head) { // 步骤 1:定位链表的后半段起点 ListNode head2 = mid(head); // 步骤 2:原地反转后半段链表 head2 = reverse(head2); // 步骤 3:同步比对前半段与反转后的后半段 // 以较短的后半段链表完全释放为循环终止标准 while (head2 != null) { if (head2.val != head.val) { return false; // 数值不匹配,判定非回文 } head2 = head2.next; head = head.next; } return true; } /** * 利用快慢指针寻找链表中点的辅助方法 */ private ListNode mid(ListNode head) { ListNode fast = head; ListNode slow = head; // 快指针每步走2格,慢指针每步走1格 while (fast != null && fast.next != null) { fast = fast.next.next; slow = slow.next; } return slow; } /** * 原地反转单链表的辅助方法 */ private ListNode reverse(ListNode head) { ListNode cur = head; ListNode pre = null; while (cur != null) { ListNode nxt = cur.next; // 暂存后继节点 cur.next = pre; // 逆转指针指向 pre = cur; // 前驱指针推进 cur = nxt; // 当前指针推进 } return pre; // 返回逆序后的新头节点 } }

六、 复杂度极限分析

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

  • 精确摊还分析

    • 定位中点模块:快指针每次步进 2,遍历完成时慢指针移动了 ⌊n/2⌋ 步。

    • 反转局部链表模块:仅对后半段长度为 ⌈n/2⌉ 的子链表进行单次遍历,耗时 ⌈n/2⌉ 步。

    • 同步线性比对模块:最多执行 ⌈n/2⌉ 次比对。

  • 结论:算法总体基本指令的执行总次数不超过 1.5n 次,时间开销与链表总长度 n 呈严格的线性正比关系。

2. 空间复杂度:O(1)

  • 分析:该算法的所有改写、翻转和比对逻辑均直接施加在传入的原始链表物理节点内存块上。执行期间,算法仅在栈内存中开辟了head2fastslowcurprenxt等有限个引用类型的局部控制变量。

  • 结论:没有申请任何与输入规模相关的外部数据结构,其分配的额外物理内存空间始终保持固定,空间复杂度为常数阶 O(1)。

http://www.jsqmd.com/news/1124576/

相关文章:

  • IS31FL3731驱动LED矩阵与PIC18F2553的实战指南
  • 基于YOLO与多模态学习的昆虫识别系统开发实践
  • oe-performance数据可视化组件开发指南:ECharts集成与定制
  • 12| 深入理解TCP协议中的动态数据传输
  • AI Agent工程落地:自主执行、工具调用与记忆管理实战
  • 6DoF运动追踪:IIM-42652 IMU与PIC18F26K40的嵌入式实践
  • 打破数学输入壁垒:MathLive如何让你的网页公式编辑变得简单又专业
  • VR技术升级与用户体验的脱节现象分析
  • 基于深度学习的猫狗表情识别系统设计与实现
  • PIC18F45K42与IS31FL3731的LED矩阵驱动设计
  • 基于YOLOv8-seg的高精度道路缺陷检测系统开发
  • 高性能直流有刷电机驱动方案设计与优化
  • YOLOv6改进:ConvNeXt V2主干网络与增强模块设计
  • 利用Amazon GuardDuty构建云上GenAI威胁检测与自动化响应体系
  • AngularJS客户端模板注入漏洞:原理、利用与根治方案
  • 基于深度学习的智能老照片修复系统设计与实现
  • 本地化AI编程工作流:基于DeepSeek与开源工具构建可控智能开发环境
  • 利用ds_store_exp工具挖掘.DS_Store文件泄露漏洞的实战指南
  • LTC6903与PIC32的数字控制振荡器设计与实现
  • AI如何革新文献综述:智能聚类与知识图谱实战
  • 量子纠错技术:原理、挑战与容错策略
  • 基于Playwright的Web自动化系统架构设计与工程实践
  • 机器学习模型优化:SSA算法与SVM参数调优实战
  • Windows 7离线安装.NET 4.7.2:手动修复“无法建立证书链”错误
  • 机器学习模型生产化部署实战:从Notebook到高可用服务
  • MC74HC165A与TM4C123GH6PZ在数字信号采集中的应用
  • AI Agent智能体开发全景指南:从理论到实践
  • Nginx与Apache实战:构建四层AI爬虫防护体系,守护网站资源
  • 本科生学术写作必备:9款AI工具全流程指南
  • JX3Toy:如何用智能脚本让剑网3操作效率提升300%