Description
Given a singly linked list, determine if it is a palindrome.
Follow up:
Could you do it in O(n) time and O(1) space?
Code
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def isPalindrome(self, head):
"""
:type head: ListNode
:rtype: bool
"""
if head == None or head.next == None:
return True
llen = lpos = 0
temp = head
while temp != None:
llen += 1
temp = temp.next
lpos = llen // 2 - 1
cnt = 0
pre = None
right = head
while cnt <= lpos:
if cnt == lpos:
right = head.next if llen % 2 == 0 else head.next.next
cnt += 1
temp = head.next
head.next = pre
pre = head
head = temp
while not pre == None:
if pre.val != right.val:
return False
pre = pre.next
right = right.next
return True
按照O(n)时间复杂度,O(1)空间复杂度做的。具体的思想就是找到中间点,然后将前面的列表反转,这样才能遍历2n次就判断出结果,同时空间复杂度是O(1)。
去讨论里看了大神们的答案,发现了精彩的讨论,哈哈哈 该题在leetcode中精彩的评论
回到问题本身,发现大神就是大神,同样的逻辑,写出来的代码更简洁,就是看不懂(其实这并不是件好事…)。先贴在下面回头看。
Code(StefanPochmann)
Solution 1: Reversed first half == Second half?
Phase 1: Reverse the first half while finding the middle.
Phase 2: Compare the reversed first half with the second half.
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
Solution 2: Play Nice
Same as the above, but while comparing the two halves, restore the list to its original state by reversing the first half back. Not that the OJ or anyone else cares.
def isPalindrome(self, head):
rev = None
fast = head
while fast and fast.next:
fast = fast.next.next
rev, rev.next, head = head, rev, head.next
tail = head.next if fast else head
isPali = True
while rev:
isPali = isPali and rev.val == tail.val
head, head.next, rev = rev, head, rev.next
tail = tail.next
return isPali
看了看,果然屌呀。的确是在做同样的事,可就是那么短的代码就完成了。找到中点的同时还将前半段给反转了,的确可以这么做,可我的确没想到能合在一起。学习学习,以后就知道了。
Conclusion
虽然是简单题,但是大神写的代码依然是和常人不一样…