在问 · 算法题解

564. 寻找最近的回文数

题目描述

输入一个字符串 n,它表示一个正整数,没有前导零。

找一个回文整数,使它与 n 所表示的数之差的绝对值尽可能小。回文整数是指十进制写法正读反读都一样的非负整数,0 也算。答案不能是 n 本身。

如果有两个回文数与 n 的距离相同,返回较小的那个。结果同样以不含前导零的字符串形式返回。

示例 1
输入:n = "123"
输出:"121"

解释:离 123 最近的回文数是 121,相差 2。

示例 2
输入:n = "1"
输出:"0"

解释:0 和 2 与 1 的距离都是 1,取较小的 0。

数据范围

  • 1 <= n.length <= 18
  • n 只由数字组成。
  • n 没有前导零。
  • n 表示的整数在 [1, 10^18 - 1] 范围内。

解题思路

回文数由前半部分完全决定,要离 n 近,前半部分就应该和 n 的前半部分 prefix 尽量接近。所以只需把 prefix-1、prefix、prefix+1 三个数分别镜像成回文。若前半加减 1 后位数变了,答案会变成位数不同的回文,这类情况由两个边界候选 99…9(m-1 位)和 10…01(m+1 位)覆盖。最后删掉 n 本身,在至多 5 个候选里按(距离,数值)取最小。

为什么正确

与 n 最近的回文一定在这 5 个候选之中:同位数的回文里,前半部分越接近 prefix 越接近 n;跨位数的最近回文只能是 99…9 或 10…01。

复杂度分析

时间 O(m),m 为位数;额外空间 O(m)。

易错点

只镜像 prefix 本身是不够的:n 若已是回文必须换别的,且 99、1000 这类数的最近回文位数不同。还要记得删除 n 本身,并在距离相同时取较小值。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def nearestPalindromic(self, n: str) -> str:
        m = len(n)
        cands = {10 ** m + 1, 10 ** (m - 1) - 1}
        prefix = int(n[:(m + 1) // 2])
        for p in (prefix - 1, prefix, prefix + 1):
            s = str(p)
            if len(s) == (m + 1) // 2:
                cands.add(int(s + s[::-1][m % 2:]))
        x = int(n)
        cands.discard(x)
        return str(min(cands, key=lambda c: (abs(c - x), c)))

载入编辑器,自己跑一遍 →

字符串 专题的其他题目

查看 字符串 全部题目 →