题目在这:https://leetcode-cn.com/problems/palindrome-linked-list/
法一:(偷懒法)
思路分析 :
可以直接将链表里的元素放到列表里,然后判断是否回文即可。
完整代码:
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
res = []
while head:
res.append(head.val)
head = head.next
return True if res == res[::-1] else False
题目中还有个进阶。
要求时间复杂度 N 空间复杂度 1。
那就意味着我们不能开辟额外的空间了,只能原地判断。
法二: (后半段翻转法)
一个链表若回文,则从中间分开,两边应该是镜像的,也就是说。我们可以直接找到中心点,然后翻转后半段的链表,再依次比较是否相等就可以了。
-
第一步找到中心点。:
使用快慢指针找中心点, 慢指针每次走一个单位,快指针每次走两个单位。这种情况下,当快指针指向最后一个元素(奇数个元素)或指向空值时(偶数个元素)慢指针刚好指向中间点(奇数个元素)或中间两个值的前一个值(偶数个元素)。
这里如果没看懂的话,随便举个例子画一下就懂了,很好理解。 -
第二步翻转后半段链表。:
关于链表的翻转,可以看我的另一篇文章,里面有详细的解释。 -
第三步依次比较元素是否相等。:
大家可以在纸上画一下,当后半段链表翻转结束后,最后一个指针应当指向了原始列表的末尾,这样我们只需要不断比较末尾指针和头指针是否相等即可,一直用 next就行了。
结束条件:其中一个指针的下一个位置是另一个指针所指位置(偶数个元素)
或者 两个指针的下一个位置指向同一个位置,(奇数个元素)
完整代码
def isPalindrome(self, head: ListNode) -> bool:
fast,slow = head,head
while True: # 找到中间点的位置
if fast.next == None: # 此时fast 指向奇数个数链表的 倒数第一个元素
break # solw指向中间节点
if fast.next.next == None: # 此时fast 指向偶数个链表的 倒数第二个元素
break # 此时slow指向中间两个节点的前一个节点
fast = fast.next.next
slow = slow.next
pre = slow.next
while pre: # 翻转后半段
temp = pre.next
pre.next = slow
slow = pre
pre = temp
while True: # 前后半段进行比较
if head.val != slow.val:
return False
if head.next == slow.next or head == slow.next:
return True
head = head.next
slow = slow.next