234. 回文链表
题目链接:234. 回文链表
题目描述
给你一个单向链表的头节点 head,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false 。
核心思考:寻找中点与原地反转
判断一个数组是否是回文很简单,首尾双指针向中间逼近即可。但在单向链表中,由于我们无法从尾部向前逆向遍历,这个问题实际上可以被拆解为三个经典的链表子操作组合:
1. 寻找中点(快慢指针)
前置知识: 这一步的详细推导可以参考我们之前做过的 876. 链表的中间结点
利用快慢指针(fast 和 slow)从头部同步起跑。快指针每次走两步,慢指针每次走一步。当快指针走到链表末尾边界时,慢指针刚好停在链表的中间位置。这一步帮助我们完美地劈开了链表的前半段和后半段。
2. 原地反转后半段链表
这就变成了常见的“反转链表”题型。以慢指针 slow 所指向的中间节点为起点,将链表的后半部分进行原地反转。反转完成后,我们就能拿到一个指向原本链表末端(即反转后首节点)的新头指针。
3. 双指针比对
到了这一步,一切都变得直观了。我们只需将一个指针指向原链表头部 head,另一个指针指向刚刚被反转的后半段头部,然后让它们同时向后游走并行验证节点的值。
由于不论链表整体长度是奇数还是偶数,反转后的后半部分节点数严格等于(甚至少于)前半部分,因此只要以后半段遍历完毕(即遇到空节点 None)作为验证结束的跳出条件,就可以完美规避边界溢出的异常。
解题思路 (Python)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
|
class Solution: def isPalindrome(self, head: Optional[ListNode]) -> bool: if not head or not head.next: return True slow = head fast = head while fast != None and fast.next != None: fast = fast.next.next slow = slow.next prev = None curr = slow while curr != None: temp = curr.next curr.next = prev prev,curr = curr,temp
p1,p2 = head,prev while p2 != None: if p1.val == p2.val: p1 = p1.next p2 = p2.next else: return False return True
|
![image-compressed.png]()
复杂度分析
- 时间复杂度:$O(N)$,其中 $N$ 是链表的节点数量。不论是快慢指针找中点、遍历后半部进行原地反转、还是最后的双指针验证比对,每个过程皆为沿着链表单向前进,整体总时间开销依然是严苛的线性级别。
- 空间复杂度:$O(1)$。我们在链表操作全过程中仅变动了部分节点的
next 指向链路,并且只定义了有限几个指针变量记录内存地址,没有开辟任何同数据规模相关的新空间。
ACM 模式
本节提供 ACM 竞赛风格的完整可运行代码,包含输入输出处理。
输入格式:
输入一行整数数组,以空格分隔。
完整代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| import sys
class Solution: def isPalindrome(self, head: Optional[ListNode]) -> bool: if not head or not head.next: return True slow = head fast = head while fast != None and fast.next != None: fast = fast.next.next slow = slow.next
prev = None curr = slow while curr != None: temp = curr.next curr.next = prev prev,curr = curr,temp
p1,p2 = head,prev while p2 != None: if p1.val == p2.val: p1 = p1.next p2 = p2.next else: return False return True
def main(): nums = list(map(int, sys.stdin.read().strip().split()))
sol = Solution() result = sol.isPalindrome(nums) print(result)
if __name__ == "__main__": main()
|
运行示例:
1
| echo "2 -1 3 4 -5" | python solution.py
|