LeetCode 9. 回文数(Easy)/ 564. 寻找最近的回文数(Hard)

在这里插入图片描述
题目链接

代码

class Solution:
    ### 0212 判断前一半的数字和后一半的数字是否相等(72 ms,14.7 MB)
    def isPalindrome(self, x: int) -> bool:
        # x为负 or x大于0且x的个位为0,直接返回False
        if x < 0 or (x > 0 and x % 10 == 0):
            return False

        res = 0

        # 若当前数x大于新数res,进行循环(只需判断一半)
        while x > res:
            res = res * 10 + x % 10
            x //= 10
        
        # 回文数长度为奇数 或 偶数
        return x == res or x == res // 10

    ### 0212 使用字符串判断(88 ms,14.9 MB)
    def isPalindrome(self, x: int) -> bool:
        return str(x) == str(x)[::-1]

564. 寻找最近的回文数

在这里插入图片描述

class Solution:
    def nearestPalindromic(self, n: str) -> str:
        """
        题目要求:给定整数的字符串n,返回与它最近(差的绝对值最小)的回文整数(不包括自身,若不止一个,返回较小的那个)
        :param n: 给定的整数n,以字符串形式给出
        :return: 返回距离n最近的回文整数
        """
        # 解题思路:题目本身不难理解,难点在于如何确定最近的那个回文数
        # 构造回文数有一个直观的方法:用原数的较高位的数字替换其对应的较低位,此时修改的都是较低位的数字,因此构造出的新的整数与原数较为接近
        # 明确了这种构造方法,那么如何找到这些备选数呢,这里采用了一种策略,可以理解为贪心
        # 实际上最近的那个数最多也就只有三种情况:
        # 用原数的前半部分替换后半部分得到的回文整数;用原数的前半部分加一后的结果替换后半部分得到的回文整数;用原数的前半部分减一后的结果替换后半部分得到的回文整数
        # 简言之,记原数的前半部分为a,就是将a、a+1、a-1为左边分别构建一个回文数,然后选择三个数中最近的那个即可(别忘记排除本身的情况)
        # 基本思路已经形成了,还需考虑一下细节和特殊情况
        # 细节1:在分割前半部分时,若长度为奇数,则多给其分一位(一个小技巧,取前(len+1)//2个,如果原来是奇数,就会多取一个,如果是偶数,则还是刚好取一半)\
        # 细节2:当长度为奇数时,a为左半边会加上中间一位,此时反转拼接时需要少拼接一位
        # 特殊情况1: 小于10的个位数时,个位数全部都是回文的,故直接返回n-1即可(n+1的距离一样近,但是要取小的)
        # 特殊情况2:n为10的整数幂时,也是直接返回n-1即可,例如:n为100,100-1=99天然回文数
        # 特殊情况3:n为11时,这是一个大坑,该方法下需要单独考虑,利用这种构造方法是得不到答案9的
        # 特殊情况4(其实可以不用单独列出,一般的构造可以包含,单独列出相当于节省时间呗):n全为9的时候,直接返回n+2
        
        if int(n) < 10 or int(n[::-1]) == 1:  # 特殊情况1、2。解释一下int(n[::-1]),逆序以后数为1,原数不就是10的整数幂咯(不难理解)
            return str(int(n) - 1)
        
        if n == '11':  # 特殊情况3
            return '9'
        
        if set(n) == {'9'}:  # 特殊情况4
            return str(int(n) + 2)

        l = len(n)  # 取长度
        a, b = n[:(l + 1) // 2], n[(l + 1) // 2:]  # 分出前半部分和后半部分(用上述小技巧完美解决细节1)
        list_a = [str(int(a) - 1), a, str(int(a) + 1)]  # 构造出a、a+1、a-1
        res = [aa + aa[len(b) - 1::-1] for aa in list_a]  # 拼接构造出备选数,反转逆序时只取b(后半部分)的长度就行,可以完美解决细节2

        # 这个排序的意思是,先按是否等于n排序(等就在后面,相当于大),在按绝对值大小排序(小的在前),这样排序后天然排除了本身,因为本身必在最后
        if n in res:
            res.remove(n)
        return min(res, key=lambda x: abs(int(x) - int(n))) # 最后返回距离最近的那个数(排除自身)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值