Check If a Sentence Reads the Same Ignoring Case and Symbols

Solve this Problem
Easy10–15 min
Topics
Companies
Practice:GFG ↗
Given a string s that may contain letters, digits, spaces, and punctuation, determine whether it reads the same forwards and backwards once you ignore case and skip every character that isn't a letter or a digit. Try to solve it by scanning inward from both ends of the original string at once, rather than building a cleaned copy first — that gets you to O(1) extra space.

Test Case 1:

Input:s = "No lemon, no melon!"
Output:true
Explanation:Ignoring case, spaces, and punctuation, the letters read "nolemonnomelon" both forwards and backwards.

Test Case 2:

Input:s = "Was it a car or a cat I saw?"
Output:true
Explanation:Cleaned down to "wasitacaroracatisaw", which reads the same in reverse.

Test Case 3:

Input:s = "Hello, World!"
Output:false
Explanation:Cleaned down to "helloworld", which is not the same forwards and backwards.

Constraints

  • 1 ≤ s.length ≤ 200
  • s consists of printable ASCII characters — letters, digits, spaces, and punctuation
🚀

Try the Dry Run

Don't just read the solution — watch it execute, one step at a time.

🧪Try your own test case
1class Solution {
2 public boolean isSentencePalindrome(String s) {
3 int left = 0, right = s.length() - 1;
4 while (left < right) {
5 while (left < right && !Character.isLetterOrDigit(s.charAt(left))) left++;
6 while (left < right && !Character.isLetterOrDigit(s.charAt(right))) right--;
7 if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) return false;
8 left++;
9 right--;
10 }
11 return true;
12 }
13}
14
N
o
l
e
m
o
n
,
n
o
m
e
l
o
n
!
left
right
Variables
left0
right18
INITIALIZE

Set left to index 0 and right to the last index, 18. We'll move them toward each other, skipping anything that isn't a letter or digit.

Step 1 / 14

Approach & Solutions

Brute Force — Build a Cleaned Copy

Brute

Walk the string once, keeping only letters and digits and lowercasing each one as you go, to build a cleaned copy. Then compare that copy to its own reverse. Simple to reason about, but it needs a second string the same size as the cleaned input just to check the answer.

TimeO(n)
SpaceO(n)
1class Solution { 2 public boolean isSentencePalindrome(String s) { 3 StringBuilder cleaned = new StringBuilder(); 4 for (char c : s.toCharArray()) { 5 if (Character.isLetterOrDigit(c)) cleaned.append(Character.toLowerCase(c)); 6 } 7 String forward = cleaned.toString(); 8 String backward = cleaned.reverse().toString(); 9 return forward.equals(backward); 10 } 11}

Optimal — Two Pointers, Skip in Place

Optimal

Skip building a second string at all. Walk two pointers inward from both ends of the original string. At each step, slide either pointer past any character that isn't a letter or digit, then compare the lowercased characters the pointers land on. Any mismatch means it's not a palindrome; if the pointers meet or cross with no mismatch found, it is.

TimeO(n)
SpaceO(1) extra
1class Solution { 2 public boolean isSentencePalindrome(String s) { 3 int left = 0, right = s.length() - 1; 4 while (left < right) { 5 while (left < right && !Character.isLetterOrDigit(s.charAt(left))) left++; 6 while (left < right && !Character.isLetterOrDigit(s.charAt(right))) right--; 7 if (Character.toLowerCase(s.charAt(left)) != Character.toLowerCase(s.charAt(right))) return false; 8 left++; 9 right--; 10 } 11 return true; 12 } 13}

Related Problems