請判斷一個鏈表是否爲迴文鏈表。
示例 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