Given a string s, return true if the s can be palindrome after deleting at most one character from it.
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
For this problem in leetcode my code has passed 462/469 test cases:
Following is the test case for which my code is failing the test.
"aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga"
My code is:
class Solution:
def validPalindrome(self, s: str) -> bool:
skip=0
l,r=0,len(s)-1
while l<r:
if s[l]==s[r]:
l =1
r-=1
elif s[l]!=s[r] and skip<1 and s[l 1]==s[r]:
l =1
skip=1
elif s[l]!=s[r] and skip<1 and s[r-1]==s[l]:
r-=1
skip=1
else:
return False
return True
What is the problem with my code?
Note: in this string the output should be true, mine returns false
From left there are characters 'lcup' and from right there are characters 'lucup' My code is supposed to skip the letter u from right side and continue.
"aguokepatgbnvfqmgm**lcup**uufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuu**pucul**mgmqfvnbgtapekouga"
Another example: It returns true for the following string:
s='adau'
Skips letter 'u' as expected.
However when I use the example according to the test case string that failed, it returns False. s= 'cuppucu'
It should skip first u from the right side and return True but it doesn't.
However as soon as I replace that last letter 'u' with letter 'a' it skips the letter 'a' and returns True. What's the problem here?
CodePudding user response:
I over-complicated this in my first answer. I thought that you had to skip a particular character multiple times. As others have pointed out, that isn't true. So you have a solution from someone else, but you wanted to know how to change your code to always do the right thing. One way would be to run your algorithm twice. The first time, you only consider if you can skip a character on the left side of the input string as you're walking over it. For the second call, you only consider skipping a character on the right side. For cases like the one you ran into here where you could choose to skip either character, but only one will produce a positive result, well then if you try both cases, one or the other will always succeed when it should.
So here's that simple change you can make...modifying your function only slightly, and then calling it twice.
class Solution:
def _validPalindrome(self, s: str, choose_first: bool) -> bool:
skip = 0
l, r = 0, len(s) - 1
while l < r:
if s[l] == s[r]:
l = 1
r -= 1
elif choose_first and s[l] != s[r] and skip < 1 and s[r - 1] == s[l]:
r -= 1
skip = 1
elif not choose_first and s[l] != s[r] and skip < 1 and s[l 1] == s[r]:
l = 1
skip = 1
else:
return False
return True
def validPalindrome(self, s: str) -> bool:
return self._validPalindrome(s, False) or self._validPalindrome(s, True)
def main():
inp = "aguokepatgbnvfqmgmlcupuufxoohdfpgjdmysgvhmvffcnqxjjxqncffvmhvgsymdjgpfdhooxfuupuculmgmqfvnbgtapekouga"
print(Solution().validPalindrome(inp))
main()
Result:
True
This should pass for all the cases for which your original code passed.
CodePudding user response:
Imagine the string 'abbab'
. First you check index 0 and 4 with the values "a" and "b". They are not the same, but the "b" at index 1 matches the "b" at index 4. So you move forward to 1 and 4. Next is 2 and 3 and those are "b" and "a" and those don't match too. End of the story.
abbab
l r
abbab
l r
abbab
lr
-> False
Now let's switch around the elif
blocks. Again you check index 0 and 4 first. They are not the same, so you now change the right index first and see that 0 and 3 are both "a". The next comparison is at indexes 1 and 2 with "b". Finished. Found a match.
abbab
l r
abbab
l r
abbab
lr
-> True
You didn't ask for it but here is a working solution with a different approach.
class Solution:
def generate_strings(self, s):
yield s, s[::-1]
for pos in range(len(s)):
t = ''.join(c for i, c in enumerate(s) if i != pos)
yield t, t[::-1]
def validPalindrome(self, p):
return any(x == y for x, y in self.generate_strings(p))