news 2026/4/16 12:10:57

力扣234.回文链表-反转后半链表

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
力扣234.回文链表-反转后半链表

问题描述

给定一个单链表的头节点head,判断该链表是否为回文链表。如果是,返回true;否则,返回false

示例 :

输入: head = [1,2,2,1] 输出: true
输入: head = [1,2] 输出: false

进阶:你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

解法一:反转后半部分链表(最优解)

这是面试中最常考的方法,时间复杂度 O(n),空间复杂度 O(1)。

算法步骤

  1. 使用快慢指针找到链表的中间节点

  2. 反转链表的后半部分

  3. 比较前半部分和反转后的后半部分

  4. 恢复链表(可选)

代码实现

class Solution { public boolean isPalindrome(ListNode head) { if(head==null||head.next==null){ return true; } ListNode mid=Find_mid(head); ListNode head2=reverse_List(mid); while(head2!=null){ if(head.val!=head2.val){ return false; } head=head.next; head2=head2.next; } return true; } private ListNode reverse_List(ListNode head){//反转链表 ListNode pre=null; ListNode cur=head; while(cur!=null){ ListNode Temp=cur.next; cur.next=pre; pre=cur; cur=Temp; } return pre; } private ListNode Find_mid(ListNode head){//找到中间节点 ListNode slow=head; ListNode fast=head; while(fast!=null&&fast.next != null){ slow=slow.next; fast=fast.next.next; } return slow; } }

关键点分析

  1. 快慢指针找中点

    • 慢指针每次走一步,快指针每次走两步

    • 当快指针到达末尾时,慢指针正好在中点

    • 对于奇数长度链表,慢指针停在中间节点

    • 对于偶数长度链表,慢指针停在中间两个节点的第二个

  2. 反转链表

    • 使用三个指针:pre、curr、Temp,cur指向pre,pre往前移,cur往前移

    • 每次迭代将当前节点的next指向前一个节点

时间复杂度与空间复杂度

  • 时间复杂度:O(n)

    • 找中点:O(n/2) ≈ O(n)

    • 反转后半部分:O(n/2) ≈ O(n)

    • 比较两部分:O(n/2) ≈ O(n)

    • 总时间:O(n)

  • 空间复杂度:O(1)

    • 只使用了常数级别的额外空间

解法二:使用栈

思路

利用栈的后进先出特性,将链表元素入栈,然后依次出栈与链表比较。

代码实现

java

class Solution { public boolean isPalindrome(ListNode head) { if (head == null || head.next == null) { return true; } Stack<Integer> stack = new Stack<>(); ListNode current = head; // 将链表值压入栈中 while (current != null) { stack.push(current.val); current = current.next; } // 比较栈顶元素和链表当前值 current = head; while (current != null) { if (current.val != stack.pop()) { return false; } current = current.next; } return true; } }

复杂度分析

  • 时间复杂度:O(n),需要遍历链表两次

  • 空间复杂度:O(n),需要额外栈空间

解法三:递归

思路

利用递归的调用栈,从链表末尾开始比较。

代码实现

java

class Solution { private ListNode frontPointer; public boolean isPalindrome(ListNode head) { frontPointer = head; return recursivelyCheck(head); } private boolean recursivelyCheck(ListNode currentNode) { if (currentNode != null) { // 递归到链表末尾 if (!recursivelyCheck(currentNode.next)) { return false; } // 比较当前节点值和前端指针的值 if (currentNode.val != frontPointer.val) { return false; } // 前端指针向后移动 frontPointer = frontPointer.next; } return true; } }

复杂度分析

  • 时间复杂度:O(n),需要递归遍历整个链表

  • 空间复杂度:O(n),递归调用栈的空间

解法四:复制到数组 + 双指针

思路

将链表值复制到数组中,然后使用双指针判断数组是否为回文。

代码实现

java

class Solution { public boolean isPalindrome(ListNode head) { // 将链表值复制到数组中 List<Integer> values = new ArrayList<>(); ListNode current = head; while (current != null) { values.add(current.val); current = current.next; } // 使用双指针判断数组是否为回文 int left = 0; int right = values.size() - 1; while (left < right) { if (!values.get(left).equals(values.get(right))) { return false; } left++; right--; } return true; } }

复杂度分析

  • 时间复杂度:O(n)

    • 复制到数组:O(n)

    • 双指针比较:O(n/2) ≈ O(n)

  • 空间复杂度:O(n),需要额外数组存储链表值

常见错误与注意事项

错误1:没有处理奇偶长度差异

java

// 错误示例:没有考虑奇偶长度差异 private ListNode findMiddle(ListNode head) { ListNode slow = head; ListNode fast = head; while (fast != null) { // 错误:应该检查fast.next slow = slow.next; fast = fast.next.next; } return slow; }

修正

java

private ListNode findMiddle(ListNode head) { ListNode slow = head; ListNode fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; } return slow; }

错误2:反转链表实现错误

修正

java

private ListNode reverseList(ListNode head) { ListNode pre = null; ListNode cur = head; while (cur != null) { ListNode temp = cur.next; cur.next = pre; pre = cur; cur = temp; } return pre; }

扩展:如果要恢复链表怎么办?

如果需要保持链表原样,可以在比较后再次反转恢复:

java

class Solution { public boolean isPalindrome(ListNode head) { if (head == null || head.next == null) return true; // 找到中点 ListNode slow = head, fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; } // 反转后半部分 ListNode secondHalf = reverseList(slow); // 比较 ListNode p1 = head, p2 = secondHalf; boolean result = true; while (p2 != null) { if (p1.val != p2.val) { result = false; break; } p1 = p1.next; p2 = p2.next; } // 恢复链表 reverseList(secondHalf); return result; } private ListNode reverseList(ListNode head) { ListNode prev = null, curr = head; while (curr != null) { ListNode nextTemp = curr.next; curr.next = prev; prev = curr; curr = nextTemp; } return prev; } }

总结

方法时间复杂度空间复杂度优点缺点
反转后半部分O(n)O(1)空间最优,满足进阶要求修改了原链表结构
使用栈O(n)O(n)实现简单,不修改原链表需要额外空间
递归O(n)O(n)代码简洁递归深度可能较大
复制到数组O(n)O(n)实现简单需要额外空间

推荐使用反转后半部分链表的方法,因为:

  1. 空间复杂度为 O(1),满足进阶要求

  2. 时间复杂度为 O(n),性能良好

  3. 是面试中最常考的解法

相关题目

  1. 反转链表:基础中的基础,必须掌握

  2. 链表的中间结点:快慢指针的经典应用

  3. 回文数字:类似的回文判断问题

  4. 回文字符串:字符串版本的回文判断

掌握这道题的关键在于理解快慢指针和链表反转这两个核心技巧,这两个技巧在链表相关题目中非常常见。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/15 16:29:43

字节内部92%工程师都在用,TRAE CN正式推出企业版

12月18日&#xff0c;字节跳动旗下AI编程工具TRAE CN企业版正式发布&#xff0c;旨在为企业提供高效、安全、可定制的AI编程解决方案。 2025年被视为AI编程元年&#xff0c;大模型在代码生成、补全、审查等场景中展现出切实的效果与价值。AI编程正在企业开发中快速普及&#x…

作者头像 李华
网站建设 2026/4/16 9:20:51

37、计算机系统性能优化全解析

计算机系统性能优化全解析 1. 内存交换与性能 在内存交换方面,有这样一个例子:每个内存占用量大的程序使用 150MB 内存,但每页仅触及 1 字节。该例子在页面大小为 4K 的奔腾 4 计算机上运行,这意味着总共有 38,400 页。换句话说,修改 37K 内存竟花费了长达 17 秒。在这个…

作者头像 李华
网站建设 2026/4/16 11:12:46

29、Ubuntu系统使用指南:从启动设置到安全优势

Ubuntu系统使用指南:从启动设置到安全优势 启动设置优化 当系统默认启动项滑落列表不再被识别时,可通过以下操作解决: 1. 打开“启动管理器”(StartUp - Manager)。 2. 重新选择Windows作为默认操作系统。 “启动管理器”还允许更改启动超时时间。默认情况下,GRUB在…

作者头像 李华
网站建设 2026/4/15 13:11:15

通信系统仿真:通信系统基础理论_(19).现代通信技术发展趋势

现代通信技术发展趋势 引言 随着信息技术的飞速发展&#xff0c;现代通信技术也在不断进步和创新。从传统的模拟通信到数字通信&#xff0c;从有线通信到无线通信&#xff0c;从单向通信到双向通信&#xff0c;从低速通信到高速通信&#xff0c;每一步都标志着技术的巨大飞跃。…

作者头像 李华
网站建设 2026/4/16 9:21:49

基于单片机的篮球计分器的设计与实现

基于单片机的篮球计分器的设计与实现 第一章 引言 篮球运动作为全球普及的体育项目&#xff0c;计分、计时与犯规统计是比赛顺利开展的核心需求。传统篮球计分方式依赖人工记录&#xff0c;存在效率低、易出错、统计不精准等问题&#xff0c;尤其在业余比赛或基层赛事中&#x…

作者头像 李华
网站建设 2026/4/16 10:17:33

基于单片机智能扫地吸尘避障小车设计

基于单片机智能扫地吸尘避障小车设计 第一章 绪论 在智能家居理念日益普及的当下&#xff0c;地面清洁设备的智能化升级成为趋势。传统手动清扫方式耗时费力&#xff0c;普通扫地机器人存在避障精度不足、清扫覆盖不全等问题&#xff0c;难以满足高效清洁需求。基于单片机的智能…

作者头像 李华