标签:
一、题目
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?
二、解析
这个还是一个回文题目,是在做完回文数字后做的。这题要判断一个链表是不是满足回文条件。
难点就在O(1),我们不能用任何形式去保存链表中的元素。最开始我想了好几种方法都不符合这个要求,比如最简单的用栈、用list,甚至将链表尾巴连到头判断头尾是否相等,这些都避免不了O(n)的空间复杂度。
和喵爷讨论,他提出了反转链表的做法。百度了一下,还真是个挺常见的数据结构操作,自己试着写了一下,思路如下:
1.首先遍历链表,得到链表长度,从而得到中点,效果:》》》》》
2.从头开始,到中点结束,反转链表,效果:《《》》》
3.从中点开始,根据奇偶情况,一个向左遍历链表,一个向右遍历链表,判断左右是否相等。
最终时间复杂度O(3n) = O(n),空间复杂度只用到了少许变量来做反转,所以是O(1)的
三、代码
1 # Definition for singly-linked list. 2 # class ListNode: 3 # def __init__(self, x): 4 # self.val = x 5 # self.next = None 6 7 class Solution: 8 # @param {ListNode} head 9 # @return {boolean} 10 def isPalindrome(self, head): 11 start = p = q = r = ListNode(0) 12 start = p = head 13 length = 0 14 isOne = False 15 16 #special cases 17 if head == None: 18 return True 19 20 else: 21 #get the length 22 while head: 23 length += 1 24 head = head.next 25 head = start 26 27 #special cases 28 if length == 1: 29 return True 30 elif length == 2: 31 if head.val == head.next.val: 32 return True 33 else: 34 return False 35 else: 36 pos = 0 37 if length % 2 == 1: 38 isOne = True 39 pos = length / 2 40 41 else: 42 isOne = False 43 pos = length / 2 - 1 44 45 #reverse the linklist to the mid 46 count = 0 47 q = p.next 48 while count < pos: 49 r = q.next #p3 = p2.next 50 q.next = p #p2.next = p1 51 p = q #p1 = p2 52 q = r #p2 = p3 53 count += 1 54 55 #check two linklist, which p is z-a and q is a-z 56 _count = 0 57 58 #偶数,acbbca类型, 59 if isOne == False: 60 while _count <= count and q: 61 if p.val == q.val: 62 p = p.next 63 q = q.next 64 _count += 1 65 else: 66 return False 67 return True 68 69 #总长为奇数,为acbca类型,p=q= 70 else: 71 p = p.next 72 print ‘!!‘ 73 while _count <= count and q: 74 if p.val == q.val: 75 p = p.next 76 q = q.next 77 _count += 1 78 else: 79 return False 80 return True
四、总结
1.在写反转的时候,最开始写错了。
#正确: count = 0 q = p.next while count < pos: r = q.next q.next = p
p = q q = r count += 1 #错误: count = 0 while count < pos: q = p.next r = q.next q.next = p
p = q q = r count += 1
错误的原因是q=p.next,最开始我把这句写进了whle循环里,这会出现什么情况呢?这里分析一下我的错误做法:
假设一个链表:【1>>2>>3】,这里p=1
反转开始,首先q=p.next=2, r=q.next=3,起到保存下指针的目的
然后q.next=p,就完成了2的下一个指向了,即:【1<=>2 3】。
然后p = q = 2, q = r = 3,循环就接着往后走了
当下一次while循环的时候,q=p.next,会发生什么事情呢?我们看【1<=>2 3】,p=2, q=3, 但是q = p.next = 2.next = 1,这样一来q就从3变成了1,然后q.next=p = 1.next=2, 所以这时q=1, p=2。那再次循环呢,p=1, q=2,所以p,q就一直在互换位置,原因就出在p.next不应该被调用。
找到了bug,p.next惹的祸,把他从while循环中提出来
还是这个链表【1>>2>>3】,这里p=1, q=2, r=3
反转开始,q.next = p,完成了反转【1<=>2 3】,然后p=q=2, q=r=3
再次循环,r=q.next=3.next = 4, q.next = 3.next = p = 2, p=q=3, q=r=4,【1<=>2<=>3, 4】,完成了2,3反转。p=3, q=4
可以看到,这里忽略了p.next不处理。
[LeetCode]#234 Palindrome Linked List
标签:
原文地址:http://www.cnblogs.com/breada/p/4723864.html