请判断一个链表是否为回文链表。
示例 1:
输入: 1->2
输出: false
示例 2:
输入: 1->2->2->1
输出: true
进阶:
你能否用 O(n) 时间复杂度和 O(1) 空间复杂度解决此题?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
O(1)的空间复杂度是一个限制性很强的条件,因此我们无法采用数组等存储链表的值后再进行判断。递归本来就属于调用栈,因此递归方法判断也被排除。
我们思考如何判断数组是否为回文串?可以设置两个指针,一个指向数组开始,一个指向数组结尾,依次向中间靠拢来判断是否是回文串。链表由于存在单向访问,无法直接像数组那样方便的用双指针法来判断。如果我们可以对链表也使用双指针法,那么就能满足空间复杂度为O(1)的要求。由于回文串可分为前半部分和后半部分,那么如果我们把链表的后半部分反转后,就能利用双指针,同时移动进行判断是否为回文串。根据这个思路,得到算法:
1、找到链表后半部分的开始节点pHeadSecondHalf;
2、反转以pHeadSecondHalf作为头节点的链表,得到反转后链表的头结点为pHeadReverseSecond;
3、利用双指针,一个指向前半部分开始节点,另一个指向pHeadReverseSecond;
4、判断双指针指向节点的值是否相等。如果相等,双指针同时向后移动,如果不相等,返回False;
5、重复步骤4,直到步骤四返回False或者双指针有一个指向空。
具体代码实现如下所示:
# 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):
if head==None or head.next==None:
return True
pSecondHalfHead = self.firstHalfEnd(head).next
pSecondHalfHead = self.reverseList(pSecondHalfHead)
return self.isEq(head, pSecondHalfHead)
def firstHalfEnd(self, head):
pFast = head
pSlow = head
while pFast.next!=None and pFast.next.next !=None:
pFast = pFast.next.next
pSlow = pSlow.next
return pSlow
def isEq(self, headOne, headTwo):
while headOne!=None and headTwo!=None:
if headOne.val!=headTwo.val:
return False
headOne = headOne.next
headTwo = headTwo.next
return True
def reverseList(self, head):
pPrev = None
pCur = head
while pCur != None:
pTmpNext = pCur.next
pCur.next = pPrev
pPrev = pCur
pCur = pTmpNext
return pPrev