LeetCode-迴文鏈表_進階

請判斷一個鏈表是否爲迴文鏈表。

示例 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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章