【力扣680】验证回文字符串Ⅱ

题目描述

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

示例

示例 1:
输入: s = “aba”
输出: true
示例 2:
输入: s = “abca”
输出: true -------解释: 你可以删除c字符。
示例 3:
输入: s = “abc”
输出: false

题解

1、双指针

我怕第一次写的,但是很麻烦

 def validPalindrome(s):
      left, right = 0, len(s)-1
       count = 0   #记录移除次数
       while left < right:
           if s[left] == s[right]:    # 满足回文要求,指针继续移动
               left += 1
               right -= 1
           elif s[left+1] == s[right]:
               count += 1
               left += 2
               right -= 1
           elif s[left] == s[right-1]:
               count += 1
               right -= 2
               left += 1
           else:
               return False

       if count >= 2:
           return False
       return True

第一次,我试图列举出所有情况,将其归类为三种情况。如图:
1)如果要删除的元素在整个字符串的左边
那么当前left指针的下一位应该和此时的right指针值得字母相同
对应elif s[left+1] == s[right]:
2)如果要删除的元素在整个字符串的右边elif s[left] == s[right-1]:
3)要删除的字符串在整个字符正中间两位:
这种情况可以归为上述情况中的任意一种

那么如果还有其他的情况,直接说明不能只删除一个字母达到回文字符串
对应else:的部分

错因分析

在分支结构有条件判断时出现错误。
if…elif…elif …并不是并列的情况,一定是第一个elif的条件不满足,才执行第二个elif

而“删除部分在字串左边”和“删除字母在字串右边”是两种并列的情况

这样就会导致s[left + 1] == s[right]s[left] == s[right - 1]这两种情况同时满足时,就会出现错误的判断。
如字串"“lcuppucul”",用上出代码会判断为第一个elif s[left + 1] == s[right]的情况,即删除部分在字串左边。但实际上删除的应该是在右边。

措施:

添加两种情况同时满足的讨论,要注意排除字母在正中间两位的情况。
s[left + 1] == s[right] and s[left] == s[right] and left != right - 1

2、暴力枚举

思路分析

一次列举出s中删除一个字母之后的字符串,看删除一个字母之后是不是回文字符串

代码实现

def is_Palindrome(s):
    left, right = 0 ,len(s) - 1
    while left <= right:
        if s[left] != s[right]:
            return False
        left += 1
        right -= 1
    return True


def func(s):
  for i in range(len(s) - 1):
      if is_Palindrome(s[:i] + s[i+1: ]):   # 如果出现回文子串,直接返回
          return True
    return False
    
     

算法分析

1)时间复杂度:O(n²),for 循环遍历一次—n,每次切片创建新字符串-----2n
2)空间按复杂度:O(n)

3、贪心算法

思路分析

如果最外面两个字母相等,则可以直接删除两端的两个字母。直接判断删除两端字母后的子串是否为回文。

每次判断两个指针指向的字符是否相同,如果相同,则更新指针,
left += 1,right -=1,然后判断更新后的指针范围内的子串是否是回文字符串。如果两个指针指向的字符不同,则两个字符中必须有一个被删除,分别判断删除左字母和右字母后是不是回文子串,有一个满足情况即可。

代码实现

def validPalindrome( s):
      def isPalindrome(low, high):
           # t1, t2 = low, high   # 不用重新赋值,因为不会修改外部变量
           while low < high:
               if s[low] != s[high]:
                   return False
               low += 1
               high -= 1
           return True

       left, right = 0, len(s)-1
       while left <= right:
           if s[left] == s [right]:
               left += 1
               right -= 1
           else:
               # 如果删除左边的、删除右边的 剩余的都不是回文,那么就不满足,返回False
               return isPalindrome(left + 1, right) or isPalindrome(left, right - 1)
       
       return True   

算法分析

1、在函数内部创建另一个函数,形成闭包。子函数不会修改原函数中的变量值。古不用重新赋值t1,t2
2、验证回文,不要直接套用之前的代码。灵活变通。字串共用同一个s,只需要传入索引即可。
否则传入新字符串,

return isPalindrome(s[left + 1: right]) or isPalindrome(s[left: right - 1])

用切片,浪费时间空间

3、return isPalindrome(left + 1, right) or isPalindrome(left, right - 1)
等价于

if isPalindrome(left + 1, right) == False and isPalindrome(left, right - 1) == False:
	return False
else:
	return True
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值