In this problem, we are given a string and our task is to create a Python function to check if a given string is a palindrome or not. A palindrome is a word, phrase, or sequence that reads the same from left to right and right to left. To solve this in Python, we typically reverse the string and compare it with the original, or we compare characters from both ends moving toward the center. For example, the string "radar", "level", and "madam" are palindromes, while "python" is not.
Compare the string with its reverse. If they are equal, the string is a palindrome. There are multiple ways to implement this in Python: slicing, built-in functions, two-pointer iteration, recursion, or using a stack.
Approach: Use Python’s slicing s[::-1] to get a reversed copy of the string and compare it with the original.
def is_palindrome_slicing(s: str) -> bool:
"""Return True if s is a palindrome (case-sensitive)."""
return s == s[::-1]
# Example usage
print(is_palindrome_slicing('radar')) # True
Output:

Explanation : Slicing s[::-1] returns a new string that is the reverse of s. This method is compact and easy to read. It creates an extra string of the same length, so it uses O(n) extra space.
reversed() + join() Use the reversed() iterator to iterate characters in reverse and join them into a string.
def is_palindrome_reversed_join(s: str) -> bool:
rev = ''.join(reversed(s))
return s == rev
# Example usage
print(is_palindrome_reversed_join('level')) # True
Output:

Explanation : reversed(s) returns an iterator that yields characters from the end. Joining its items produces the reversed string for comparison. Functionally similar to slicing but slightly more explicit.
Use two indices, one at the start and one at the end, and compare characters while moving them towards the center. Stops early on mismatch and does not allocate a reversed string.
Code:
def is_palindrome_two_pointer(s: str) -> bool:
i, j = 0, len(s) - 1
while i < j:
if s[i] != s[j]:
return False
i += 1
j -= 1
return True
# Example usage
print(is_palindrome_two_pointer('madam')) # True
Explanation : The two-pointer approach checks matching characters pairwise and returns False on the first mismatch. It uses O(1) extra space and O(n) time, so it’s preferred when memory allocation should be minimized.
Check the first and last characters; if they match, recursively check the substring that excludes them.
def is_palindrome_recursive(s: str) -> bool:
if len(s) <= 1:
return True
if s[0] != s[-1]:
return False
return is_palindrome_recursive(s[1:-1])
# Example usage
print(is_palindrome_recursive('a')) # True
Explanation : Recursion expresses the idea clearly but creates new substring objects for each call (s[1:-1]) and may hit recursion depth limits for very long strings. Time complexity is O(n), auxiliary space is O(n) because of recursion stack and substrings.
n is the length of the string (two-pointer checks roughly n/2 character comparisons but still O(n)).reversed()+join() allocate O(n) extra space.