這題一開始我寫出來的答案通過了 22/31 個測試,卡在一個很簡單的輸入:"0P"。我的程式回傳 True,正確答案是 False。找到 bug 的過程,讓我徹底理解了 Two Pointers 的思維。
題目
給一個字串,只考慮英文字母和數字(忽略大小寫、忽略所有其他符號),判斷它是不是回文(Palindrome)。
第一版:通過 22/31,卡在 "0P"
我的第一個想法:先把字串整理成只含英文字母的 list,再反轉比較。
i >= "A" and i <= "z"這個範圍檢查是用 ASCII 碼比較。問題在於字串已經 .lower() 過,所以全是小寫。但條件寫的是 "A" 而非 "a"。
題目說「英文字母和數字都要考慮」,但我的版本把數字全過濾掉了。只要有數字的測試案例都可能答錯。
除了 Bug,還有個問題:多餘的空間
就算修好 Bug,第一版還是建立了兩個額外的 list(arr 和 arr2),空間複雜度 O(n)。判斷回文根本不需要額外空間——Two Pointers 可以做到 O(1)。
Two Pointers 的核心思維
兩個指針,一個從左、一個從右,向中間靠攏。每次比較左右兩個字元是否相同,不同就回傳 False,相同就繼續往中間走。
Best Solution:Two Pointers
s[l].isalnum() 正確處理英文字母 和 數字,沒有 ASCII 範圍的問題isalnum() vs 手動範圍判斷
Python 內建的字串方法,比自己寫 ASCII 範圍判斷更可靠、更易讀:
Two Pointers 的使用時機
Palindrome 只是 Two Pointers 的入門。這個模式能解的題型很多:
從兩端向中間
Valid Palindrome、Container With Most Water
快慢指針(Slow & Fast)
Linked List Cycle、Remove Duplicates
固定間距
Remove Nth Node From End
分割條件(Partition)
3Sum、Sort Colors
踩坑的那次 "0P" 讓我記住:永遠用語言內建的方法(isalnum())而不是自己推 ASCII 範圍。內建方法有完整的邊界處理,自己推很容易遺漏。