Leetcode 234. 迴文連結串列 快慢指標+連結串列逆序實現O(n)時間複雜度且O(1)空間複雜度

一隻黃燜雞發表於2020-11-26

題目要求

判斷一個連結串列是否為迴文連結串列。

解題思路

不限制時間複雜度的情況下是非常簡單的題目,可以有多種方法完成本題。

如果限制了 O ( n ) O(n) O(n) 時間複雜度且 O ( 1 ) O(1) O(1) 空間複雜度那麼可以按照以下思路。

連結串列題中看到 O ( n ) O(n) O(n) 時間複雜度且 O ( 1 ) O(1) O(1) 空間複雜度可以考慮快慢指標就相當於陣列題看到 O ( n ) O(n) O(n) 時間複雜度且 O ( 1 ) O(1) O(1) 空間複雜度可以考慮雙指標一樣。

那麼從快慢指標開始思考。我們知道,快慢指標可以找連結串列的中點。迴文連結串列只需要對連結串列中點兩邊進行比較就可以知道結果,因此先用快慢指標找到連結串列的中點。

找到中點以後需要令前半部分末尾等於 N o n e None None,因此為了方便起見,前半部分找到中點左邊的一個點,就停止。假設中間節點是 m e d i a n median median,我們希望 s l o w slow slow 停留在 m e d i a n median median 的左邊第一個節點,這樣我們只要令 s l o w . n e x t = N o n e slow.next = None slow.next=None 就可以得到左半部分連結串列。

此時右半部分連結串列只需要令 c u r = s l o w . n e x t cur = slow.next cur=slow.next,這樣 c u r cur cur 就是右半連結串列。

利用雙指標反轉連結串列的方式,反轉連結串列之後進行比較節點的值就可以得到結果。在比較的時候,我們之前這樣處理以後,右半部分一定不大於左半部分的長度,因此遍歷右半部分,這樣如果連結串列長度是奇數的時候,不需要考慮中間節點。

以下用多張圖具體說明這個過程:

  • 連結串列長度是奇數

ppt1.jpg2.ppt2.jpg3.ppt3.jpg4.ppt4.jpg5.ppt5.jpg6.ppt6.jpg7.ppt7.jpg8.ppt8.jpg9.ppt9.jpg10.ppt10.jpg11.ppt11.jpg12.ppt12.jpg13.ppt13.jpg

  • 連結串列長度是偶數時,可以嘗試用同樣的方式處理

程式碼

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        if not head:
            return True
        fast = slow = head
        while fast.next and fast.next.next:
            fast = fast.next.next
            slow = slow.next
        pre = None
        cur = slow.next
        slow.next = None
        while cur:
            tmp = cur.next
            cur.next = pre
            pre = cur
            cur = tmp
        while pre:
            if head.val != pre.val:
                return False
            head = head.next
            pre = pre.next
        return True

複雜度分析

時間複雜度  O ( n ) O(n) O(n) 其中 n n n 是連結串列的長度
空間複雜度  O ( 1 ) O(1) O(1) 沒有使用額外空間

工作之餘刷刷題寫寫題解,我的Leetcode主頁

https://leetcode-cn.com/u/airesearcherjhm/

相關文章