🐍1.7Different Ways to Check for a Palindrome in Python

 

Different Ways to Check for a Palindrome in Python

Introduction

A palindrome is a word, phrase, number, or sequence that reads the same forward and backward, such as madam, racecar, or 12321.

Checking for palindromes is a common problem in programming and can be solved in multiple ways. In this blog, we will explore different techniques to determine if a given string is a palindrome.


1. Using String Slicing ([::-1])

Code:

def is_palindrome_slicing(s):
    return s == s[::-1]  # Reverse the string and check equality

print(is_palindrome_slicing("madam"))  # True
print(is_palindrome_slicing("hello"))  # False

Logic Used:

  • s[::-1] reverses the string.
  • If the reversed string is the same as the original, it's a palindrome.

Explanation:

  • This is the easiest and most readable method.
  • Time Complexity: O(n), where n is the length of the string.
  • Space Complexity: O(n), since a new reversed string is created.

2. Using a Two-Pointer Approach

Code:

def is_palindrome_two_pointer(s):
    left, right = 0, len(s) - 1  # Initialize two pointers
    while left < right:  
        if s[left] != s[right]:  # Compare characters from both ends
            return False  # If mismatch found, not a palindrome
        left += 1  # Move left pointer right
        right -= 1  # Move right pointer left
    return True  # If no mismatches, it's a palindrome

print(is_palindrome_two_pointer("madam"))  # True
print(is_palindrome_two_pointer("hello"))  # False

Logic Used:

  • Use two pointers: one at the beginning (left), and one at the end (right).
  • Move both pointers inward while checking if characters match.

Explanation:

  • Efficient as it avoids creating a new string.
  • Time Complexity: O(n), as each character is checked once.
  • Space Complexity: O(1), since no extra space is used.

3. Using Recursion

Code:

def is_palindrome_recursive(s):
    if len(s) <= 1:  # Base case: A single character or empty string is always a palindrome
        return True
    if s[0] != s[-1]:  # Compare first and last character
        return False
    return is_palindrome_recursive(s[1:-1])  # Recursive call with inner substring

print(is_palindrome_recursive("madam"))  # True
print(is_palindrome_recursive("hello"))  # False

Logic Used:

  • Recursively compare the first and last characters.
  • Reduce the string by removing first and last characters in each step.

Explanation:

  • Base Case: When the string is of length 0 or 1, it's a palindrome.
  • Time Complexity: O(n).
  • Space Complexity: O(n) (due to recursive function calls).

4. Using reversed() and join()

Code:

def is_palindrome_reversed(s):
    return s == "".join(reversed(s))  # Reverse string and compare

print(is_palindrome_reversed("madam"))  # True
print(is_palindrome_reversed("hello"))  # False

Logic Used:

  • reversed(s) creates an iterator for the reversed string.
  • "".join(reversed(s)) converts it back to a string.
  • Compare with the original string.

Explanation:

  • Alternative way to reverse a string without slicing.
  • Time Complexity: O(n).
  • Space Complexity: O(n).

5. Using collections.deque (Optimal for Large Inputs)

Code:

from collections import deque

def is_palindrome_deque(s):
    d = deque(s)  # Convert string to deque for fast popping
    while len(d) > 1:
        if d.popleft() != d.pop():  # Compare first and last element
            return False
    return True

print(is_palindrome_deque("madam"))  # True
print(is_palindrome_deque("hello"))  # False

Logic Used:

  • deque (double-ended queue) allows efficient removal from both ends.
  • Uses popleft() (remove first) and pop() (remove last) for comparison.

Explanation:

  • More efficient than slicing for large datasets.
  • Time Complexity: O(n).
  • Space Complexity: O(1), as no extra string is created.

Comparison of Methods

Method Logic Used Time Complexity Space Complexity
String Slicing ([::-1]) Reverse string and compare O(n) O(n)
Two-Pointer Approach Compare characters from both ends O(n) O(1)
Recursion Reduce string size recursively O(n) O(n) (stack memory)
Using reversed() Reverse using reversed() iterator O(n) O(n)
Using deque Efficient pop operations from both ends O(n) O(1)

Summary Table

Method Code Snippet Logic Used Explanation
String Slicing ([::-1]) return s == s[::-1] Reverse the string using slicing Compares original and reversed string
Two-Pointer Approach while left < right: if s[left] != s[right]: return False Compare characters from both ends Uses two pointers (left, right) moving inward
Recursion if s[0] != s[-1]: return False; return is_palindrome(s[1:-1]) Recursively reduce the string Calls function on substring without first and last characters
Using reversed() return s == "".join(reversed(s)) Reverse using reversed() iterator Converts reversed iterator back to string and compares
Using deque d = deque(s); while len(d) > 1: if d.popleft() != d.pop(): return False Use deque for fast removals Removes first and last characters efficiently for comparison

Conclusion

Each method has its pros and cons:

  • For small strings: [::-1] slicing is the easiest and most readable.
  • For large inputs: Two-pointer (while left < right) or collections.deque is more efficient.
  • For recursion lovers: The recursive approach is elegant but inefficient for deep recursion.
  • For optimized performance: deque is the best for large datasets.

Which method do you prefer? Let me know in the comments! 🚀

Comments

Popular posts from this blog

🌐Filtering and Copying Files Dynamically in Azure Data Factory (ADF)

🔥Apache Spark Architecture with RDD & DAG

🖥️☁️AWS Athena, AWS Lambda, AWS Glue, and Amazon S3 – Detailed Explanation