Write a function to check if a given string is a palindrome. Implement solutions for: (a) Case-sensitive, (b) Case-insensitive, (c) Ignoring spaces and special characters.
#algorithm#string#palindrome#dart#two-pointer
Answer
Overview
A palindrome is a string that reads the same forwards and backwards. Examples: "racecar", "madam", "A man a plan a canal Panama" (ignoring spaces/case). This fundamental string problem tests two-pointer techniques, string processing, and edge case handling.
Approach 1: Two-Pointer (Case-Sensitive)
Most efficient approach using two pointers from opposite ends.
dartbool isPalindrome(String str) { if (str.isEmpty) return true; int left = 0; int right = str.length - 1; while (left < right) { if (str[left] != str[right]) { return false; } left++; right--; } return true; } void main() { print(isPalindrome('racecar')); // true print(isPalindrome('hello')); // false print(isPalindrome('madam')); // true }
Time Complexity: O(n) - iterate through half the string Space Complexity: O(1) - only pointer variables
Approach 2: String Reversal
Reverse and compare - simpler but uses more memory.
dartbool isPalindromeReverse(String str) { String reversed = str.split('').reversed.join(''); return str == reversed; } void main() { print(isPalindromeReverse('racecar')); // true print(isPalindromeReverse('hello')); // false }
Time Complexity: O(n) Space Complexity: O(n) - creates reversed string
Approach 3: Case-Insensitive
Convert to lowercase before checking.
dartbool isPalindromeCaseInsensitive(String str) { str = str.toLowerCase(); int left = 0, right = str.length - 1; while (left < right) { if (str[left++] != str[right--]) return false; } return true; } void main() { print(isPalindromeCaseInsensitive('Racecar')); // true print(isPalindromeCaseInsensitive('MadAm')); // true }
Approach 4: Alphanumeric Only
Ignore spaces and special characters.
dartbool isPalindromeAlphanumeric(String str) { String cleaned = str .toLowerCase() .replaceAll(RegExp(r'[^a-z0-9]'), ''); int left = 0, right = cleaned.length - 1; while (left < right) { if (cleaned[left++] != cleaned[right--]) return false; } return true; } void main() { print(isPalindromeAlphanumeric( 'A man, a plan, a canal: Panama')); // true print(isPalindromeAlphanumeric('race a car')); // false }
Time: O(n) | Space: O(n)
Complete Solution
dartclass PalindromeChecker { static bool caseSensitive(String str) { int left = 0, right = str.length - 1; while (left < right) { if (str[left++] != str[right--]) return false; } return true; } static bool caseInsensitive(String str) { str = str.toLowerCase(); int left = 0, right = str.length - 1; while (left < right) { if (str[left++] != str[right--]) return false; } return true; } static bool alphanumericOnly(String str) { str = str.toLowerCase().replaceAll(RegExp(r'[^a-z0-9]'), ''); int left = 0, right = str.length - 1; while (left < right) { if (str[left++] != str[right--]) return false; } return true; } }
Comparison
| Approach | Time | Space | Best For |
|---|---|---|---|
| Two-pointer | O(n) | O(1) | Production |
| Reversal | O(n) | O(n) | Prototypes |
| Case-insensitive | O(n) | O(n) | User input |
| Alphanumeric | O(n) | O(n) | NLP tasks |
Edge Cases
dartvoid testEdgeCases() { assert(isPalindrome('') == true); // Empty assert(isPalindrome('a') == true); // Single assert(isPalindrome('ab') == false); // Different assert(isPalindrome('abba') == true); // Even assert(isPalindrome('aba') == true); // Odd }
Best Practices
1. Handle Nulls
dartbool isPalindromeSafe(String? str) { if (str == null || str.isEmpty) return true; // ... palindrome logic }
2. Make Configurable
dartbool isPalindrome(String str, { bool ignoreCase = false, bool alphanumericOnly = false, }) { if (ignoreCase) str = str.toLowerCase(); if (alphanumericOnly) str = str.replaceAll(RegExp(r'[^a-z0-9]'), ''); int left = 0, right = str.length - 1; while (left < right) { if (str[left++] != str[right--]) return false; } return true; }