Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignoring cases.
For example,
"A man, a plan, a canal: Panama"
is a palindrome.
"race a car"
is not a palindrome.
Note:
Have you consider that the string might be empty? This is a good question to ask during an interview.
For the purpose of this problem, we define empty string as valid palindrome.
驗證回文字符串是比較常見的問題,所謂回文,就是一個正讀和反讀都一樣的字符串,比如“level”或者“noon”等等就是回文串。但是這里,加入了空格和非字母數字的字符,增加了些難度,但其實原理還是很簡單:只需要建立兩個指針,left和right, 分別從字符的開頭和結尾處開始遍歷整個字符串,如果遇到非字母數字的字符就跳過,繼續往下找,直到找到下一個字母數字或者結束遍歷,如果遇到大寫字母,就將其轉為小寫。等左右指針都找到字母數字時,比較這兩個字符,若相等,則繼續比較下面兩個分別找到的字母數字,若不相等,直接返回false.
時間復雜度為O(n), 代碼如下:
解法一:
class Solution { public: bool isPalindrome(string s) { int left = 0, right = s.size() - 1 ; while (left < right) { if (!isAlphaNum(s[left])) ++left; else if (!isAlphaNum(s[right])) --right; else if ((s[left] + 32 - 'a') %32 != (s[right] + 32 - 'a') % 32) return false; else { ++left; --right; } } return true; } bool isAlphaNum(char &ch) { if (ch >= 'a' && ch <= 'z') return true; if (ch >= 'A' && ch <= 'Z') return true; if (ch >= '0' && ch <= '9') return true; return false; } };
我們也可以用系統自帶的判斷是否是數母字符的判斷函數isalnum,參見代碼如下;
解法二:
class Solution { public: bool isPalindrome(string s) { int left = 0, right = s.size() - 1 ; while (left < right) { if (!isalnum(s[left])) ++left; else if (!isalnum(s[right])) --right; else if ((s[left] + 32 - 'a') %32 != (s[right] + 32 - 'a') % 32) return false; else { ++left; --right; } } return true; } };
對於該問題的擴展,還有利用Manacher算法來求解最長回文字符串問題,參見我的另一篇博文Manacher's Algorithm 馬拉車算法。
參考資料:
https://discuss.leetcode.com/topic/5581/here-s-a-clean-c-solution/2
https://discuss.leetcode.com/topic/25405/my-three-line-java-solution