Problem Description
A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers.
Given a string s, return true if it is a palindrome, or false otherwise.
Examples
Example 1: Input: s = "A man, a plan, a canal: Panama" Output: true Explanation: "amanaplanacanalpanama" is a palindrome. Example 2: Input: s = "race a car" Output: false Explanation: "raceacar" is not a palindrome. Example 3: Input: s = " " Output: true Explanation: s is an empty string "" after removing non-alphanumeric characters. Since an empty string reads the same forward and backward, it is a palindrome.
Python Solution
def isPalindrome(s: str) -> bool:
# Convert to lowercase and remove non-alphanumeric characters
filtered_chars = [c.lower() for c in s if c.isalnum()]
# Compare string with its reverse
return filtered_chars == filtered_chars[::-1]
Java Solution
class Solution {
public boolean isPalindrome(String s) {
// Two pointers from both ends
int left = 0;
int right = s.length() - 1;
while (left < right) {
// Skip non-alphanumeric characters from left
while (left < right && !Character.isLetterOrDigit(s.charAt(left))) {
left++;
}
// Skip non-alphanumeric characters from right
while (left < right && !Character.isLetterOrDigit(s.charAt(right))) {
right--;
}
// Compare characters
if (Character.toLowerCase(s.charAt(left)) !=
Character.toLowerCase(s.charAt(right))) {
return false;
}
left++;
right--;
}
return true;
}
}
C++ Solution
class Solution {
public:
bool isPalindrome(string s) {
// Two pointers from both ends
int left = 0;
int right = s.length() - 1;
while (left < right) {
// Skip non-alphanumeric characters from left
while (left < right && !isalnum(s[left])) {
left++;
}
// Skip non-alphanumeric characters from right
while (left < right && !isalnum(s[right])) {
right--;
}
// Compare characters
if (tolower(s[left]) != tolower(s[right])) {
return false;
}
left++;
right--;
}
return true;
}
};
JavaScript Solution
/**
* @param {string} s
* @return {boolean}
*/
var isPalindrome = function(s) {
// Convert to lowercase and remove non-alphanumeric characters
s = s.toLowerCase().replace(/[^a-z0-9]/g, '');
// Two pointers from both ends
let left = 0;
let right = s.length - 1;
while (left < right) {
if (s[left] !== s[right]) {
return false;
}
left++;
right--;
}
return true;
};
C# Solution
public class Solution {
public bool IsPalindrome(string s) {
// Two pointers from both ends
int left = 0;
int right = s.Length - 1;
while (left < right) {
// Skip non-alphanumeric characters from left
while (left < right && !Char.IsLetterOrDigit(s[left])) {
left++;
}
// Skip non-alphanumeric characters from right
while (left < right && !Char.IsLetterOrDigit(s[right])) {
right--;
}
// Compare characters
if (Char.ToLower(s[left]) != Char.ToLower(s[right])) {
return false;
}
left++;
right--;
}
return true;
}
}
Complexity Analysis
- Time Complexity: O(n) where n is the length of the string
- Space Complexity: O(1) as we only use two pointers
Solution Explanation
This solution uses a two-pointer approach:
- Key concept:
- Character filtering
- Two-pointer comparison
- Case insensitive
- Algorithm steps:
- Skip non-alphanumeric
- Convert to lowercase
- Compare characters
- Move pointers
Key points:
- Handle empty strings
- Skip special characters
- Case insensitive comparison
- Efficient traversal