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) 会修改原链表结构 对空间有严格要求的场景

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

相关推荐
_Jimmy_4 分钟前
Python 协程库如何使用以及有哪些使用场景
python
aqi0027 分钟前
15天学会AI应用开发(十七)使用LangGraph实现会话记忆功能
人工智能·python·大模型·ai编程·ai应用
第一程序员43 分钟前
Rust Agent 子进程执行:Command 之前,先定义输入和超时
python·rust·github
skywalk81631 小时前
设计并实现段言的 C FFI 绑定机制 @Trae
c语言·开发语言·python·编程
weixin_BYSJ19871 小时前
SpringBoot + MySQL 乒乓球运动员信息管理系统项目实战--附源码04954
java·javascript·spring boot·python·django·flask·php
海石1 小时前
1563分的简单题,可能就简单在能被暴力AC
算法·leetcode
海石1 小时前
1400分的dp汗流浃背之【交替子数组计数】
算法·leetcode
奋发向前wcx1 小时前
P2590 树的统计 题目解析
数据结构·算法·深度优先
imbackneverdie2 小时前
AI4S不止于分子药物:以MedPeer为代表的科研基建打开产业新增量
大数据·人工智能·算法·aigc·科研·学术·ai 4s
EQUINOX13 小时前
【论文阅读】| MoCo精读
论文阅读·人工智能·python·深度学习·机器学习