題目描述:給定一個單向鏈結串列的頭節點 head,判斷該鏈結串列是否為回文串列(從前往後讀與從後往前讀相同)。要求時間複雜度 O(n),空間複雜度 O(1)。
解題思路:核心思路分三步驟。第一步,使用快慢指標找到鏈結串列的中間節點:慢指標每次走一步,快指標每次走兩步,當快指標到達尾端時,慢指標恰好在中間。第二步,將後半段鏈結串列就地反轉。第三步,同時從頭部和反轉後的後半段起始位置逐一比對節點值,若全部相符則為回文。為了不破壞原始結構,可在比對完畢後再將後半段反轉回來(題目不要求但是良好實踐)。
時間複雜度:O(n) — 找中間點需要 O(n/2),反轉後半段需要 O(n/2),比對需要 O(n/2),三個步驟合計為 O(n)。
空間複雜度:O(1) — 所有操作皆在原始串列上就地執行,只使用了有限個指標變數,不需要額外的陣列或堆疊。
1. Handle edge case: if list has 0 or 1 node, return true 2. Find middle: - Initialize slow = head, fast = head - While fast and fast.next exist: advance slow by 1, fast by 2 - slow now points to the start of the second half 3. Reverse second half in-place: - Initialize prev = null, curr = slow - While curr exists: save next, point curr.next to prev, advance prev and curr - prev is the new head of the reversed second half 4. Compare: - Initialize left = head, right = prev - While right exists: if left.val != right.val, return false; advance both 5. (Optional) Restore original list by reversing second half again 6. Return true
方法一:使用額外陣列 時間複雜度:O(n),空間複雜度:O(n) — 先將所有節點值存入陣列,再用雙指標從兩端向中間比對。實作簡單直觀,但犧牲了 O(1) 空間的要求。
方法二:使用堆疊(Stack) 時間複雜度:O(n),空間複雜度:O(n) — 先遍歷整個串列並將所有值推入堆疊,再從頭遍歷串列,每次與堆疊頂端彈出的值比對。若全部相符則為回文。此法空間同樣為 O(n)。
方法三:遞迴法 時間複雜度:O(n),空間複雜度:O(n)(遞迴呼叫堆疊) — 使用遞迴到達串列尾端後,在回溯過程中與從頭部逐步推進的指標比對。程式碼精簡但隱式使用了 O(n) 的呼叫堆疊空間,在面試中需說明其空間代價。