Palindrome After Deleting At Most One Character
Solve this Problems, return true if it can become a palindrome by deleting at most one character.
Walking two pointers inward from both ends handles the matching characters for free. The only real decision point is the first mismatch: since only one deletion is allowed, there are exactly two ways to fix it — drop the character at the left pointer, or drop the one at the right pointer. Whichever choice leaves a palindrome in the remaining range makes the answer true. Checking both candidate ranges still keeps the whole algorithm at O(n), since every character is visited only a small, constant number of times.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ s.length ≤ 10⁵ - ◆
s consists of lowercase English letters only
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public boolean canBeAPalindromeAfterOneRemoval(String s) { |
| 3 | int left = 0, right = s.length() - 1; |
| 4 | while (left < right) { |
| 5 | if (s.charAt(left) != s.charAt(right)) { |
| 6 | boolean skipLeft = isPalindromeRange(s, left + 1, right); |
| 7 | boolean skipRight = isPalindromeRange(s, left, right - 1); |
| 8 | return skipLeft || skipRight; |
| 9 | } |
| 10 | left++; |
| 11 | right--; |
| 12 | } |
| 13 | return true; |
| 14 | } |
| 15 | private boolean isPalindromeRange(String s, int left, int right) { |
| 16 | while (left < right) { |
| 17 | if (s.charAt(left) != s.charAt(right)) return false; |
| 18 | left++; |
| 19 | right--; |
| 20 | } |
| 21 | return true; |
| 22 | } |
| 23 | } |
| 24 |
04Set left to 0 and right to the last index, 4. Move them toward each other until a mismatch appears.
Approach & Solutions
Brute Force
BruteTry removing each index in turn, building the string that remains, and check whether that shorter string is a palindrome. If any single removal produces a palindrome, the answer is true. Correct, but it rebuilds and re-checks a whole new string for every one of the n possible removals.
O(n²)O(n)1class Solution {
2 public boolean canBeAPalindromeAfterOneRemoval(String s) {
3 int n = s.length();
4 for (int i = 0; i < n; i++) {
5 String candidate = s.substring(0, i) + s.substring(i + 1);
6 boolean ok = true;
7 int left = 0, right = candidate.length() - 1;
8 while (left < right) {
9 if (candidate.charAt(left) != candidate.charAt(right)) { ok = false; break; }
10 left++;
11 right--;
12 }
13 if (ok) return true;
14 }
15 return false;
16 }
17}Optimal — Two Pointers
OptimalWalk two pointers inward from both ends. While characters match, keep moving inward — that costs nothing extra. The moment a mismatch appears, there are only two possible fixes: skip the left character, or skip the right one. Check whether the remaining range is a palindrome under either choice; if either works, the answer is true. Each character is visited a small, constant number of times, so the whole check runs in O(n).
O(n)O(1)1class Solution {
2 public boolean canBeAPalindromeAfterOneRemoval(String s) {
3 int left = 0, right = s.length() - 1;
4 while (left < right) {
5 if (s.charAt(left) != s.charAt(right)) {
6 boolean skipLeft = isPalindromeRange(s, left + 1, right);
7 boolean skipRight = isPalindromeRange(s, left, right - 1);
8 return skipLeft || skipRight;
9 }
10 left++;
11 right--;
12 }
13 return true;
14 }
15 private boolean isPalindromeRange(String s, int left, int right) {
16 while (left < right) {
17 if (s.charAt(left) != s.charAt(right)) return false;
18 left++;
19 right--;
20 }
21 return true;
22 }
23}