Time complexity: O(n)
Space complexity: O(1)
想法:将linked list对半切开,分为first half和second half,再将second half倒转并与first half进行比较。比较完成后,将second half还原并与first half相连。
代码:
# 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:
#如果linked list只有一个node,返回True。
if head.next == None:
return True
#在将linked list对半切开时,我们需要找到中间点。
#建立两个指针,慢指针每次移动一步,快指针每次移动两步。
#当linked list的长度为偶数时,快指针最后会指向None,慢指针会指向second half的第一个node。
slow_ptr = head
fast_ptr = head
#记录慢指针指向的前一个node,它最后会作为first half的结尾。
prev_of_slow_ptr = head
#当linked list的长度为奇数时,快指针最后会指向链表最后一个node,慢指针会指向恰好位于中间的node。
#我们在比较first half与second half时,不需要考虑中间这个node,所以用midNode表示。
midNode = None
res = True
#用两个指针遍历这个链表。
while fast_ptr != None and fast_ptr.next != None:
fast_ptr = fast_ptr.next.next
prev_of_slow_ptr = slow_ptr
slow_ptr = slow_ptr.next
#如果快指针最后不等于None,证明链表长度是奇数。
#我们将中间点表示为midNode,把慢指针移后一位,指向second half的开头。
if fast_ptr != None:
midNode = slow_ptr
slow_ptr = slow_ptr.next
second_half = slow_ptr
#切断first half和second half。
prev_of_slow_ptr.next = None
#将second half倒转。
second_half = self.reverse(second_half)
#比较first half和second half。
res = self.compare(head, second_half)
#将second half还原。
second_half = self.reverse(second_half)
#将second half与first half相连。
if midNode != None:
prev_of_slow_ptr.next = midNode
midNode.next = second_half
else:
prev_of_slow_ptr.next = second_half
return res
def reverse(self, half_list):
prev = None
current = half_list
next = None
while (current != None):
next = current.next
current.next = prev
prev = current
current = next
new_half_list = prev
return new_half_list
def compare(self, head1, head2):
temp1 = head1
temp2 = head2
while temp1 != None and temp2 != None:
if temp1.val == temp2.val:
temp1 = temp1.next
temp2 = temp2.next
else:
return False
if temp1 == None and temp2 == None:
return True
return False