Skip to content

Practice problem

Valid Palindrome

Easy

Solve in Python · graded against 3 sample tests and a hidden test set in your browser · Published

Interactive solution

Solve Valid Palindrome

Run tries the first sample. Submit checks every sample and additional cases. Your code is saved in this browser.

Ctrl/Cmd+Enter to run

Press Esc then Tab to move keyboard focus out of the code editor.

Ready
Output will appear here after you run your code.

Problem Statement

You're given a single line of text that can mix letters, digits, spaces, and punctuation in any combination of upper and lower case. Decide whether that line is a palindrome once you ignore everything except letters and digits, and once you treat uppercase and lowercase letters as identical. Print true if, after that cleanup, the line reads the same from left to right as it does from right to left, and print false otherwise.

Input Format

The input is exactly one line: the string to check. That line can be empty (zero characters), and when it isn't empty it can include upper- and lowercase English letters, digits 0-9, spaces, and punctuation marks such as commas, periods, apostrophes, and colons. Read the whole line exactly as given — the spaces and punctuation are still part of the line even though the comparison itself will skip over them.

Output Format

Print exactly one line containing the word true or the word false, in lowercase and with no surrounding quotes or extra text. Print true if the cleaned-up version of the input (letters and digits only, lowercased) is a palindrome, and false if it is not.

Example Walkthrough

Use the first sample, Madam, in Eden: I'm Adam. Picture two pointers, one starting at the first character (index 0, M) and one at the last character (index 23, the final m). Both are letters, so we lowercase and compare them: m equals m, a match, and both pointers move one step inward. This continues character by character — a/a, then d/d, then a/A (equal once lowercased) — until the right pointer lands on the space at index 19. A space isn't a letter or digit, so the right pointer skips over it and lands on m at index 18, which matches the left pointer's m at index 4. Now the left pointer has to skip too: it steps past the comma at index 5 and the space at index 6 to reach i at index 7, while the right pointer steps past the apostrophe at index 17 to reach I at index 16 — another match. Next the right pointer sits on the space at index 15 and then the colon at index 14, skips both, and lands on n at index 13, which matches the left pointer's n at index 8. One more skip on the left, past the space at index 9, brings E at index 10 up against e at index 12. The pointers then meet at the d in the middle (index 11). Since every pair that was compared matched and the pointers met without ever finding a mismatch, the line is a palindrome, so we print true.

Approach

One way to solve this is to build a cleaned-up copy of the string first: walk through the original line once, keep only the characters where .isalnum() is true, lowercase each of them, and collect the results into a new string. Once you have that cleaned string, checking whether it's a palindrome is just a matter of comparing it to its own reverse. This is easy to reason about, but it uses extra space proportional to the length of the input, since you're storing a whole second copy of it.

The two-pointer technique avoids that extra copy. Keep one index starting at the front of the original string and another starting at the back, and move them toward each other. At each step, if the character under the left pointer isn't a letter or digit, advance just the left pointer past it without comparing anything yet; do the same for the right pointer if its character isn't a letter or digit. Once both pointers are sitting on a letter or digit, compare them case-insensitively — if they differ, you can stop immediately and report false, since a single mismatch is enough to rule out a palindrome. If they match, move both pointers one step further inward and repeat.

The moment the two pointers meet or cross, every pair of characters that could possibly mismatch has already been checked and none of them did, so the string is confirmed to be a palindrome and you can print true. Skipping non-alphanumeric characters in place, rather than removing them into a new string first, is what keeps this version from needing any extra memory beyond the original input and a couple of index variables.

Common Mistakes

  • Filtering with a check that excludes digits. It's easy to write a condition that only keeps letters (for example, checking .isalpha() instead of .isalnum()), forgetting that digits also count as alphanumeric characters for this problem. A short input like 0P shows the difference clearly: correctly keeping both characters gives 0p, which reversed is p0 — not a match, so the answer is false — but dropping the digit leaves only p, a single character that trivially looks like a palindrome.
  • Comparing characters without lowercasing them first. If you compare text[left] to text[right] directly instead of comparing their lowercased forms, a perfectly valid palindrome where the case differs between the two matching positions — like the capital M that opens Madam lining up with the lowercase m that ends Adam — will be reported as a mismatch even though it shouldn't be.
  • Skipping only one non-alphanumeric character at a time with a single if instead of a loop. Punctuation and spaces often appear back-to-back, like the : in Eden: I'm. If your pointer-skipping logic only steps past one such character before immediately trying to compare, it will end up comparing a space or punctuation mark against a letter and report a false mismatch — the skipping step needs to keep advancing the pointer until it actually lands on a letter or digit.

Constraints

  • The input line has between 0 and 1,000 characters.
  • The line may contain uppercase and lowercase English letters, digits, spaces, and punctuation characters.
  • Only letters and digits count toward the comparison; case is ignored, so 'A' and 'a' are treated as the same character.

Target complexity

Time: O(n) — the two pointers together move across the string once, so every character is visited a constant number of times as the pointers step inward.

Space: O(1) — the two-pointer approach only needs a fixed number of index variables and does not build any extra copy of the string.

Sample tests

Sample 1

Input

Madam, in Eden: I'm Adam

Expected output

true

Removing spaces and punctuation and lowercasing everything gives "madaminedenimadam", which reads the same forwards and backwards.

Sample 2

Input

Step on pets

Expected output

false

Removing the spaces and lowercasing gives "steponpets"; reversed that is "stepnopets". The first four letters agree, but the fifth character is "o" one way and "n" the other, so the line is not a palindrome.

Sample 3

Input

Was it a car or a cat I saw?

Expected output

true

Removing spaces and punctuation and lowercasing everything gives "wasitacaroracatisaw", which reads the same forwards and backwards.

Read the idea first

More problems

All practice problems →