打败算法 —— 回文链表
本文参考
出自LeetCode上的题库 —— 回文链表,本题比较简单,但既考察了单向链表反转,也可以应用快慢指针
https://leetcode-cn.com/problems/palindrome-linked-list/
回文链表问题
给定一个单链表的头节点 head ,请你判断该链表是否为回文链表。如果是,返回 true ;否则,返回 false
示例1:
输入: head = [1,2,2,1]
输出: true
示例2:
输入:head = [1,2]
输出:false
解题思路
第一种解法和"环形链表 II"相似,我们可以额外用一个列表存储各个节点的值,遍历完链表后,判断列表中的元素是否构成回文(Python的语法糖可以用一行代码实现)
第二种解法利用快慢指针,将第一种解法的$O(n)$空间复杂度降低到了$O(1)$。在"环形链表 II"中,我们利用快慢指针计算相遇位置公式,而在本题中,我们仍然利用 $d_{fast}=2d_{slow}$ 的性质,当快指针到达链表的末尾时,慢指针正好停留在中间节点的位置。注意,根据不同的限制条件,慢指针所在节点的值可能是回文的前半部分,也可能是回文的后半部分
得到中间位置后,只需倒置后半部分的节点链接方向,就能够完成回文的判断
O(n)空间复杂度解法
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
class Solution:
def is_palindrome_1(self, head: ListNode) -> bool:
if head is None:
return False
# 记录所有节点的值
curr_node = head
node_values = list()
while curr_node:
node_values.append(curr_node.val)
curr_node = curr_node.next
# 判断是否是回文
# node_num = len(node_values)
# for i in range(node_num // 2):
# if node_values[i] != node_values[node_num - i - 1]:
# return False
# return True
# 利用语法糖完成回文判断
return node_values == node_values[::-1]
O(1)空间复杂度解法(快慢指针)
def is_palindrome_2(self, head: ListNode) -> bool:
if head is None:
return False
slow = head
fast = head
# 使用快慢指针找到中间节点
while fast.next is not None and fast.next.next is not None:
slow = slow.next
fast = fast.next.next
# 反转后半段单向链表
pre = None
while slow:
next_node = slow.next
slow.next = pre
pre = slow
slow = next_node
# 判断是否是回文
tail = pre
while head:
if head.val != tail.val:
return False
head = head.next
tail = tail.next
return True