Python判断回文数及进阶

判断回文是一个很基础同时也很经典的问题,首先我们来了解一下何谓回文?
引入百度百科的解释:

“回文”是指正读反读都能读通的句子,它是古今中外都有的一种修辞方式和文字游戏,如“我为人人,人人为我”等。在数学中也有这样一类数字有这样的特征,成为回文数(palindrome number)。 [1]
设n是一任意自然数。若将n的各位数字反向排列所得自然数n1与n相等,则称n为一回文数。例如,若n=1234321,则称n为一回文数;但若n=1234567,则n不是回文数。 [1]
注意:
1.偶数个的数字也有回文数124421
2.小数没有回文数

那么 在计算编程中我们如何写一段程序来判断一个字符串是否符合回文的特征呢?
请看示例,题目来自于leetcode125.
在这里插入图片描述
代码如下:

class Solution:
    def isPalindrome(self, s: str) -> bool:
        # 定义new_s保存 对s进行处理过后的新s
        new_s = ''
        # s首先去掉所有空格并都转化为小写
        for i in s.replace(' ', '').lower():
            # 若 i 属于[a,z] or [0,9],则并入新字符串,此举主要是为了去掉标点
            if (i >= 'a' and i <= 'z') or (i >= '0' and i <= '9'):
                new_s += i
        # 定义双指针l,r 分别指向new_s头尾
        l, r = 0, len(new_s)-1
        while l < r:
            # 回文数特征是首位各位依次相等,若不满足此条件,直接返回False
            if new_s[l] != new_s[r]:
                return False
            # 首尾指针分别向后/向前移动
            l += 1
            r -= 1
        # 若首尾指针相遇时依然没有提前返回False,则此串一定为回文串,返回True即可
        return True

可以看出,判断回文串的关键在于利用指向头尾的双指针来分别对首尾各位依次判断。
接下来我们看下稍稍进阶的一题,题目来自leetcode680
在这里插入图片描述
由于上面的经验,我们很容易能写出双指针的代码,但请注意,此题发生了一点小的变化,它允许最多删除一个字符,顾名思义,即它给了这个字符串一次机会,如果它本来就是回文串,那么ok皆大欢喜,我们之前的方法拿来即用,若它不是,我们可以有一次机会选择删掉某一个字符,再来判断这个新的字符串是否为回文串。
很容易想到暴力的方法,即对每一位字符做一次while l < r 操作,只要其中有一次是回文,那么我们就返回True,否则返回False。但是题目中给出了串长,50000.so 此路不通。
我们回到之前的讨论,可以看出,此题关键在于我们应该如何选择删掉字符继续匹配,为了寻找如何删除的思路,我们先写出一个删掉一个字符后可以变成回文串的例子,观察其规律。例如:
在这里插入图片描述
容易看出,这个字符串我们删除字符 ‘b’ 或者字符 ‘c’ 都能使其变为回文串,根据双指针移动的规律,我们不难看出,‘b’ 与 ‘c’ 正是此时 l 与 r 指针所指向的字符。于是我们可以这样尝试,首先正常匹配,当出现一次失效匹配时,我们尝试删除左指针指向的字符,即新串为区间为 [l+1, r] ,同理我们删去右指针指向的字符,即新串区间为 [l, r-1],我们对这两个串在进行一次匹配,由于它的机会已耗尽,所以若这两个串都不是回文,那么我们就可以断定原字符串无法在至多修改一次的条件下变为回文字符串。
代码如下:

class Solution:
    def validPalindrome(self, s: str) -> bool:
        def checkPalindrome(low, high):
            l, r = low, high
            while l < r:
                if s[l] != s[r]:
                    return False
                l += 1
                r -= 1
            return True

        l, r = 0, len(s) - 1
        # 若s[l] == s[r],则继续循环,否则对l+1 与 l-1调用checkPalindrome,
        # 即可判断 最多删除一个字符的情况下 是否为回文字符串
        while l < r:
            if s[l] == s[r]:
                l += 1
                r -= 1
            else:
                return checkPalindrome(l + 1, r) or checkPalindrome(l, r - 1)
        return True

End

猜你喜欢

转载自blog.csdn.net/airenKKK/article/details/106221348