LeetCode hot100:234 回文链表:快慢指针巧判回文链表

问题描述:

给你一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false进阶: 你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?

示例1:

**输入:**head = [1,2,2,1]

**输出:**true

示例2:

**输入:**head = [1,2]

**输出:**false

解决方法:

方法一:数组+双指针

算法思路:

  1. 遍历链表,将节点值复制到数组中;

  2. 使用双指针法判断数组是否为回文。

代码实现:

python 复制代码
def isPalindrome(head):
    values = []
    curr = head
    while curr:
        values.append(curr.val)
        curr = curr.next
    
    left, right = 0, len(values) - 1
    while left < right:
        if values[left] != values[right]:
            return False
        left += 1
        right -= 1
    return True

复杂度分析:

  • 时间复杂度:O(n),需要遍历链表和数组各一次
  • 空间复杂度:O(n),需要额外的数组空间存储节点值

方法二:快慢指针+翻转

算法思路:

  1. 使用快慢指针找到链表中点;

  2. 反转后半部分链表;

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

代码实现:

python 复制代码
# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def isPalindrome(self, head: Optional[ListNode]) -> bool:
        # 快慢指针
        if not head or not head.next:
            return True
        fast = low = head
        # 查找反转的起点
        while fast and fast.next:
            low = low.next
            fast = fast.next.next
        # 反转后半部分链表
        prev = None
        cur = low
        while cur: # 迭代反转
            nxt = cur.next
            cur.next = prev
            prev = cur
            cur = nxt
        # 链表比较
        left = head
        right = prev
        while right:
            if left.val != right.val:
                return False
            left = left.next
            right = right.next
        return True

复杂度分析:

  • 时间复杂度:O(n),遍历链表的次数是常数倍
  • 空间复杂度:O(1),只使用了几个指针变量

问题详解:

以链表 [ 1,2,3,2,1]为例说明方法二:

1、快慢指针找中点:

  • 慢指针每次走1步,快指针每次走2步;
  • 最终慢指针会停在节点3上。

2、反转后半部分:

  • 将 [3,2,1]反转为[1,2,3];
  • 此时链表的结构被修改,但比较阶段不需要完整的结构。

3、比较前后部分:

  • 前半部分: [1,2,3];
  • 后半部分(反转后):[1,2,3];
  • 逐个比较对应节点值。

关键点说明

  • 为什么在比较部分要使用 ++while right:++后半部分长度总是整体的一部分,小于等于前半部分长度,确保只比较必要的节点对数;
  • 链表的结构改变:方法二会改变链表的结构,但是比较完成后通常不需要恢复;
  • 边界情况处理:空链表和单节点链表直接返回 true。

总结:

| 方法 | 优点 | 缺点 | 适用情况 |
| 数组+双指针 | 思路简单,不易出错 | 需要额外O(n)空间 | 对空间要求不高的场景 |

快慢指针+翻转 空间复杂度O(1) 会修改原链表结构 对空间有严格要求的场景

通常情况下期望掌握第二种方法,因为它展示了更多的链表操作技巧。

相关推荐
子夜四时歌14 分钟前
Python详细安装与环境搭建
开发语言·python
Jinkxs15 分钟前
SkyWalking - Python 应用追踪:基于 skywalking-python 的埋点
开发语言·python·skywalking
大头博士先生15 分钟前
【3月考】二级Python最新真题及满分代码合集(基本操作题部分)
开发语言·python
白狐_79816 分钟前
【实战架构】一人抵一家设计公司:基于 ComfyUI + Python RPA + Photoshop 的全自动化工业制图工作流
python·photoshop·rpa
shengli72216 分钟前
Python在金融科技(FinTech)中的应用
jvm·数据库·python
xcLeigh17 分钟前
IoTDB Python原生接口全攻略:从基础读写到高级实战
开发语言·数据库·python·api·iotdb·原生接口·读写数据
User_芊芊君子17 分钟前
文科生封神!Python+AI 零门槛变现:3 天造 App,指令即收入(附脉脉 AI 沙龙干货)
开发语言·人工智能·python
MeowNeko17 分钟前
为什么说程序员重命名时电脑不要带中文?记一次python manage.py runserver时UnicodeDecodeError的原因与解决方案
人工智能·python·chatgpt·中间件·django·utf8
是Dream呀17 分钟前
2025年中秋月亮只有94.91%圆?Python告诉你真相
开发语言·python·中秋节
星辰徐哥18 分钟前
Python开发从入门到精通:异步编程与协程
开发语言·python