Problem Statement
Given a string s
, return true
if the string can be a palindrome after deleting at most one character.
LeetCode
Constraints
1 <= s.length <= 10^5
s consists of lowercase English letters.
Examples
Example 1:
Input: s = "aba"
Output: true
Example 2:
Input: s = "abca"
Output: true
Explanation: You could delete the character 'c'.
Example 3:
Input: s = "abc"
Output: false
Different Approaches
1️⃣ Brute Force Approach
🔍 Intuition:
- Try removing each character one by one.
- For each deletion, check if the resulting string is a palindrome.
Code:
class Solution {
public:
bool isPalindrome(string& s) {
int left = 0, right = s.size() - 1;
while (left < right) {
if (s[left++] != s[right--]) return false;
}
return true;
}
bool validPalindrome(string s) {
if (isPalindrome(s)) return true;
for (int i = 0; i < s.length(); i++) {
string temp = s.substr(0, i) + s.substr(i + 1);
if (isPalindrome(temp)) return true;
}
return false;
}
};
Complexity Analysis:
- Time Complexity:
O(n^2)
- Checking
n
substring each of length up ton
- Checking
- Space Complexity:
O(n)
- For each substring copy
2️⃣ Two Pointers Approach
🔍 Intuition:
- A palindrome reads the same forward and backward.
- You are allowed to remove at most one character, so as soon as a mismatch occurs, you have 2 choices:
- Skip the left character
- Skip the right character
- If either results in a palindrome, return true.
🧠 Algorithm:
- Use two pointers: left = 0, right = n - 1
- If characters match, move inward.
- On mismatch:
- Try skipping left → check isPalindrome(left+1, right)
- Try skipping right → check isPalindrome(left, right-1)
- Return true if either is a palindrome.
Code:
class Solution {
public:
// Helper function to check if a given substring is a palindrome
// It takes a string `s` and two indices: left and right
bool isPalindrome(string& s, int left, int right) {
while (left < right) {
// If characters at left and right don't match, it's not a palindrome
if (s[left] != s[right]) return false;
// Move inward
left++;
right--;
}
// If loop completes, it's a palindrome
return true;
}
// Main function to check if the string can be a palindrome
// by removing at most one character
bool validPalindrome(string s) {
int left = 0;
int right = s.length() - 1;
// Use two pointers from both ends
while (left < right) {
// If characters match, move both pointers inward
if (s[left] == s[right]) {
left++;
right--;
} else {
// If characters don't match:
// Try skipping one character either from left or right,
// and check if the rest forms a palindrome
// Case 1: skip the left character (left + 1)
// Case 2: skip the right character (right - 1)
// If either case returns true, it's valid
return isPalindrome(s, left + 1, right) || isPalindrome(s, left, right - 1);
}
}
// If no mismatches are found or valid by removing one character
return true;
}
};
⏱ Complexity Analysis:
- Time Complexity:
O(n)
— one pass + possible one more partial pass - Space Complexity:
O(1)
3️⃣ Recursive Approach
🔍 Intuition:
- Use recursion to try both deletions and check for validity.
- At each mismatch, recurse with one character skipped.
Code:
class Solution {
public:
// Recursive helper function to check if a string can be a palindrome
// with at most one character deletion
bool helper(string& s, int left, int right, int deleteCount) {
// If we've already deleted more than one character, return false
if (deleteCount > 1) return false;
// Use two pointers to compare characters from both ends
while (left < right) {
if (s[left] == s[right]) {
// If characters match, move both pointers inward
left++;
right--;
} else {
// If characters don't match:
// Try both deletion options:
// 1. Delete character at `left` and recurse
// 2. Delete character at `right` and recurse
// Increment deleteCount in each recursive call
return helper(s, left + 1, right, deleteCount + 1) ||
helper(s, left, right - 1, deleteCount + 1);
}
}
// If loop completes or a valid path is found, return true
return true;
}
// Main function to start the process with 0 deletions so far
bool validPalindrome(string s) {
return helper(s, 0, s.length() - 1, 0);
}
};
⏱ Complexity Analysis:
- Time Complexity:
O(n)
- Worst case O(n) (limited depth recursion)
- Space Complexity:
O(n)
(recursion stack in worst case)