Python中的Palindrome链表与O(1)额外空间

时间:2016-06-13 14:35:36

标签: python algorithm linked-list palindrome

这是#234 Leetcode问题:

  

鉴于单链表,确定它是否是回文。

     

跟进:你能在O(n)时间和O(1)空间吗?

使用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):
    current = None

    def isPalindrome(self, head):
        """
        :type head: ListNode
        :rtype: bool
        """
        if not head or not head.next:
            return True

        self.current = head

        return self.compare(head)

    def compare(self, head):
        if not head: return True

        if not self.compare(head.next): return False

        if head.val != self.current.val:
            return False
        else:
            self.current = self.current.next
            return True

这适用于小样本,但提供

  

超出最大递归深度

任何人都可以只使用O(1)空间提供解决方案吗?谢谢。

2 个答案:

答案 0 :(得分:4)

如果允许您修改列表,可以执行以下操作:

  1. 遍历列表以计算有多少元素。
  2. 第二次迭代,从列表中间开始,反转列表节点中的指针,使它们指向上一个节点而不是下一个节点。记住最后一个节点。
  3. 现在你有一个指向第一个节点和最后一个节点的指针,并且可以从任一端向中间迭代,直到找到差异(没有回文)或到达中间(回文)。
  4. 反转下半场的指针,让它们回到原来的状态。
  5. 这只需要不变的额外空间,并且具有线性执行时间。

答案 1 :(得分:0)

我评论了解决方案的关键点:

class Solution:
    def with_array(self,head:ListNode)->bool:
        # this makes S:O(N)
        nums=[]
        while head:
            nums.append(head.val)
            head=head.next
        l,r=0,len(nums)-1
        while l<=r:
            if nums[l]!=nums[r]:
                return False
            l+=1
            r-=1
        return True

    def optimum(self,head:ListNode)->bool:
        fast_pointer=head
        slow_pointer=head
        # I wanna reach the end of the linked list. I stop when fast_pointer.next=None
        while fast_pointer and fast_pointer.next:
            # we are forwarding fast_pointer twice
            fast_pointer=fast_pointer.next.next
            # while slow reach middle, fast will reach to the end
            slow_pointer=slow_pointer.next
            # at the end of this while loop, slow_pointer will be in middle, fast_pointer will be at the end
        
        # reverse the second half of the list, from slow_pointer till the fast_pointer
        # at the end of the reverse, prev will point to the last node 
        prev=None
        while slow_pointer:
            temp=slow_pointer.next
            slow_pointer.next=prev
            # eventually prev will point to the last node
            prev=slow_pointer
            slow_pointer=temp
        # check if it is a palindrome
        # remember, after reversing, prev=tail
        left,right=head,prev
        while right:
            if left.val!=right.val:
                return False
            left=left.next
            right=right.next
        return True