LeetCode 680. 验证回文字符串 Ⅱ | Python

744

680. 验证回文字符串 Ⅱ


题目来源:leetcode-cn.com/problems/va…

题目


给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例 1:

输入: "aba"
输出: True

示例 2:

输入: "abca"
输出: True
解释: 你可以删除c字符。

注意:

  • 字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。

解题思路


思路:双指针

题目中说明,允许【最多删除一个字符】。先抛开这个,说一下在不删除的情况下,如果去判断一个字符串是否是回文字符串?

同样的,常见的方法是双指针。定义双指针,一个指向开始,一个指向末尾。这时,判断指针所对应的字符是否相同,如果不同,则不是回文字符串;如果相同,则指针都往中间移动,再次判断,直到指针相遇,这时就可以确认这个字符是回文字符串。

现在题目中说明,可以允许删除一个字符,这里我们同样使用双指针的方法。双指针的初始化也同样,一个指向开始,一个指向末尾。这个时候同样是判断指针对应的字符是否相同,如果相同,跟前面的步骤一样,指针往中间移动继续判断,直至指针相遇。

不同的地方在于,如果当前双指针对应的字符不同时,可以考虑删除一个元素,在这里可以分为两种情况:

  • 删除左指针对应的字符,移动左指针到后一位,再次判断这个时候左指针所对应字符到右指针所对应字符这个范围的字符串是否是回文字符串
  • 删除右指针对应的字符,移动右指针到前一位,再次判断左指针所对应字符到这时的右指针所对应字符这个范围的字符串是否是回文字符串

根据前面的两种情况,假设定义双指针为 left, right。如果此时 left 和 right 指针对应的字符不同时,上面的两种情况就应该表示为:

  • 移动左指针到后一位,即是判断:s[left+1]...s[right] 之间的字符串是否是回文字符串
  • 移动有指针到前一位,即是判断:s[left]...s[right-1] 之间的字符串是否是回文字符串

具体的代码实现如下。

代码实现


class Solution:
    def validPalindrome(self, s: str) -> bool:
        def check(left, right):
            # 判断是否是回文数
            while left < right:
                if s[left] != s[right]:
                    return False
                left += 1
                right -= 1
            return True
        
        # 定义指针,一个指向开始,一个指向末尾
        left, right = 0, len(s) - 1
        while left < right:
            # 指针所对应的字符相同时,指针往中间移动
            if s[left] == s[right]:
                left += 1
                right -= 1
            # 指针所对应的字符不同,考虑删除一个字符
            # 1. 删除当前左指针的字符,移动至后一位
            # 2. 删除当前右指针的字符,移动至前一位
            # 重新判断删除字符后,字符串是否是回文字符串
            else:
                return check(left + 1, right) or check(left, right - 1)
        return True

实现结果


实现结果


总结

  • 使用双指针的方法,定义双指针,一个指向开始的位置,一个指向末尾。判断指针对应的字符是否相同。相同则往中间移动指针,继续判断直至指针相遇。不同则考虑删除一个字符,具体如下。
  • 删除左指针的字符,移动左指针至后一位,重新判断此时字符串。
  • 删除右指针的字符,移动右指针至前一位,重新判断。
  • 只要上面两种情况,其中一个符合都返回 True,否则返回 False。

欢迎关注微信公众号《书所集录》