Search code examples
pythonstringreversepalindrome

What's wrong with my code?Valid Palindrome 2- Leetcode 680


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?


Solution

  • 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.