#125. Valid Palindrome
題目描述
回文指的是一組片語,在把所有大寫字母轉換成小寫並且移除非字母與數字(non-alphanumeric)的字元後,由前向後、由後向前的字元排列都是一樣的。Alphanumeric
字元指的是任何的字母或數字。
給你一個字串s
,如果是回文則回傳true
,不是則回傳false
。
限制條件
- 1 <= 字串
s
長度 <= 2*10^5 s
由ASCII字元所組成。
解題思路
回文的意思題目應該說明得很清楚了,就是由前向後讀會和由後向前讀一樣。 那麼剩下的工作就該如何比對字串的內容了。
字串處理 String Filter
按照步驟來的話,可以很直覺的得出先處理字串,接著檢查字串是否符合回文結構。
步驟如下:
- 排除不是字母、不是數字的字元。
- 把所有大寫字母轉換成小寫。
- 檢查字串內的字元是否符合回文結構。
- 回傳結果。
public class Solution {
public bool IsPalindrome(string s) {
s = StringFilter(s);
int left=0;
int right=s.Length-1;
while(left<=right){
if(left>=right) return true;
if(s[left]!=s[right]) return false;
left++;
right--;
}
return true;
}
public string StringFilter(string s) {
var t = new StringBuilder(s);
int idx = 0;
while(idx<t.Length){
if(!Char.IsLetterOrDigit(t[idx])){
t.Remove(idx,1);
continue;
}
idx++;
}
for(int i=0;i<t.Length;i++){
t[i] = Char.ToLower(t[i]);
}
return t.ToString();
}
}
複雜度分析:
- 時間複雜度:
StringFilter
最差的情況會花費O(2n)的時間,比對字元則會花費O(n/2)的時間,共花費(2n+n/2)的時間,因此時間複雜度為O(n)。 - 空間複雜度:
StringFilter
會建立一個StringBuilder
來修剪字串,使用的空間取決於s
的長度,因此空間複雜度為O(n)。
雙指標 Two Pointers
在上面的解法中,我們先對字串進行處裡,之後再比對處理後的字串內容。
但事實上,我們可以直接比對字串的內容,並且略過那些不符合規則要求的字元,不需要額外去修改字串。
進行字元檢查時,我們設置了兩個指標left
和right
,由於回文的規則,left
和right
所指向的字元應該要一致。
如果不進行字串的處理,指標很可能會指到不符合規則的字元上,因此在開始字元比對之前,先將指標移動到符合規則的字元上,就可以順利比對正確的字元了。
步驟:
- 設置左右指標。
- 確認左右指標指在符合規則的字元上,反之則移動指標直到找到正確的字元或者超出限制的邊界。
- 兩邊都找到正確的字元後,將字元都轉換為小寫再進行比對。
- 重複2、3步驟,直到完成回文的檢查。
public class Solution {
public bool IsPalindrome(string s) {
//
int left=0;
int right=s.Length-1;
while(left<=right){
while(!Char.IsLetterOrDigit(s[left]) && left<right) left++;
while(!Char.IsLetterOrDigit(s[right]) && left<right) right--;
if(left>=right) return true;
if(Char.ToLower(s[left])!=Char.ToLower(s[right])) return false;
left++;
right--;
}
return true;
}
}
複雜度分析:
- 時間複雜度:最差的情況會花費掉s.Length/2的時間,因此時間複雜度為O(n)。
- 空間複雜度:沒有使用到會增長空間的資料結構,因此空間花費為O(1)。
學習重點
- 學習如何去操作字串。
- 雙指標(Two Pointers)的應用。