题目
请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
思路
我想到了要将链表逆序,然后再比较前一半和后一半,但我没想到怎么找到中点,有点没转过来脑筋。所以就用了比较笨的方法,空间复杂度高,时间还好。先求出列表长度,然后走一半压栈,然后一个个弹出和后面的比较。
代码:
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
lenth = 0
stack = []
temp1 = temp2 = head
while temp1:
lenth += 1
temp1 = temp1.next
if lenth%2 == 0:
for i in range(lenth/2):
stack.append(temp2.val)
temp2 = temp2.next
for j in range(lenth/2):
item = stack.pop()
if item == temp2.val:
temp2 = temp2.next
else:
return False
return True
else:
for i in range((lenth-1)/2):
stack.append(temp2.val)
temp2 = temp2.next
temp2 = temp2.next
for j in range((lenth-1)/2):
item = stack.pop()
if item == temp2.val:
temp2 = temp2.next
else:
return False
return True
优化:
思路上来说就是将前一半的反向,然后和后一半进行比较,用了一个小trick,就是用了一个fast标记一次走两步,slow一次走一步,则fast走的是第奇数个节点,这样当fast and not fast.next为真的时候,就说明长度为奇数,并且slow在正中间,如果not fast为真的时候,说明长度为偶数,slow在中间两个相同数字的第二个。
代码:
def isPalindrome(self, head):
rev = None
slow = fast = head
while fast and fast.next:
fast = fast.next.next
rev, rev.next, slow = slow, rev, slow.next
if fast:
slow = slow.next
while rev and rev.val == slow.val:
slow = slow.next
rev = rev.next
return not rev
附上评论区一段比较好的解释:
def isPalindrome(self, head):
# rev records the first half, need to set the same structure as fast, slow, hence later we have rev.next
rev = None
# initially slow and fast are the same, starting from head
slow = fast = head
while fast and fast.next:
# fast traverses faster and moves to the end of the list if the length is odd
fast = fast.next.next
# take it as a tuple being assigned (rev, rev.next, slow) = (slow, rev, slow.next), hence the re-assignment of slow would not affect rev (rev = slow)
rev, rev.next, slow = slow, rev, slow.next
if fast:
# fast is at the end, move slow one step further for comparison(cross middle one)
slow = slow.next
# compare the reversed first half with the second half
while rev and rev.val == slow.val:
slow = slow.next
rev = rev.next
# if equivalent then rev become None, return True; otherwise return False
return not rev