題目在問什麼
給一條單向 linked list,判斷它是否為回文。
例子
Input: 1 -> 2
Output: false
Input: 1 -> 2 -> 2 -> 1
Output: true
題目的進階要求
題目追問能不能做到:
- 時間複雜度
O(n) - 空間複雜度
O(1)
所以如果直接把整條 linked list 複製到陣列再雙指標比對,雖然能做,但不符合 follow-up。
解題思路
這份寫法走的是經典三步:
- 用快慢指標找到 linked list 中點
- 把後半段反轉
- 從前半段和反轉後的後半段同步往前比對
如果每個對應位置的值都相同,這條 linked list 就是回文。
為什麼這樣可行
快指標一次走兩步,慢指標一次走一步。當快指標到尾端時,慢指標剛好會停在中間附近。
之後把慢指標開始的後半段反轉,就能讓:
- 前半段從頭往後走
- 後半段從尾往前走
這兩邊在單向 linked list 上也能被線性比較。
代碼
public class Solution
{
public bool IsPalindrome(ListNode head)
{
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null)
{
fast = fast.next.next;
slow = slow.next;
}
fast = head;
slow = Reverse(slow);
while (slow != null && fast != null)
{
if (fast.val != slow.val) { return false; }
fast = fast.next;
slow = slow.next;
}
return true;
}
ListNode Reverse(ListNode node)
{
ListNode prev = null;
ListNode curr = node;
while (curr != null)
{
ListNode originNext = curr.next;
curr.next = prev;
prev = curr;
curr = originNext;
}
return prev;
}
}
複雜度
- 時間複雜度:
O(n) - 空間複雜度:
O(1)
這題先記住的重點
- 回文 linked list 的標準解法就是「找中點 + 反轉後半 + 對比」
- 快慢指標是這題的基礎
- follow-up 的重點在於不要額外開陣列或堆疊