Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Check if the characters in a string form a Palindrome in O(1) extra space in Python
A palindrome reads the same forwards and backwards. When checking if a string forms a palindrome, we often need to ignore non-letter characters and focus only on alphabetic characters. This problem requires solving it in O(1) extra space, meaning we cannot create additional data structures.
So, if the input is like s = "ra$5ce58car", then the output will be True, as the letters form "racecar" which is a palindrome.
Algorithm
We use a two-pointer approach with helper functions to find the next valid letter from both ends ?
- Use two pointers: left (start) and right (end)
- Find the next letter character from the left side
- Find the next letter character from the right side
- Compare characters at both positions
- Move pointers inward and repeat until they meet
Helper Functions
We need two helper functions to locate the next alphabetic character from each direction ?
def first_letter_index(s, left, right):
"""Find the first letter character from left to right"""
for i in range(left, right + 1):
if s[i].islower():
return i
return -1
def last_letter_index(s, left, right):
"""Find the last letter character from right to left"""
for i in range(left, right - 1, -1):
if s[i].islower():
return i
return -1
# Test the helper functions
text = "ra$5ce58car"
print("First letter from index 0:", first_letter_index(text, 0, len(text)-1))
print("Last letter from index", len(text)-1, ":", last_letter_index(len(text)-1, 0, text))
First letter from index 0: 0 Last letter from index 8: 8
Complete Solution
def first_letter_index(s, left, right):
for i in range(left, right + 1):
if s[i].islower():
return i
return -1
def last_letter_index(s, left, right):
for i in range(left, right - 1, -1):
if s[i].islower():
return i
return -1
def is_palindrome(s):
left = 0
right = len(s) - 1
while left < right:
# Find next letter from left
left = first_letter_index(s, left, right)
# Find next letter from right
right = last_letter_index(right, left, s)
# If no more letters found
if left == -1 or right == -1:
break
# Compare characters
if s[left] != s[right]:
return False
# Move pointers inward
left += 1
right -= 1
return True
# Test with examples
test_cases = ["ra$5ce58car", "hello", "a!b@a", "racecar", "abc$cba"]
for test in test_cases:
result = is_palindrome(test)
letters_only = ''.join(c for c in test if c.islower())
print(f"'{test}' ? letters: '{letters_only}' ? {result}")
'ra$5ce58car' ? letters: 'racecar' ? True 'hello' ? letters: 'hello' ? False 'a!b@a' ? letters: 'aba' ? True 'racecar' ? letters: 'racecar' ? True 'abc$cba' ? letters: 'abccba' ? False
How It Works
The algorithm maintains O(1) space complexity by using only two pointers and helper function variables. Here's the step-by-step process ?
- Step 1: Initialize left=0, right=length-1
- Step 2: Find the next lowercase letter from the left
- Step 3: Find the next lowercase letter from the right
- Step 4: Compare the characters at these positions
- Step 5: If they match, move pointers inward and repeat
- Step 6: If they don't match, return False
Space and Time Complexity
| Complexity | Value | Explanation |
|---|---|---|
| Time | O(n) | Each character visited at most once |
| Space | O(1) | Only pointer variables used |
Conclusion
This solution efficiently checks palindromes in O(1) extra space using two pointers. The key is using helper functions to skip non-letter characters while maintaining constant space complexity.
