📌  相关文章
📜  将给定数转换为回文数所要减去的最小数(1)

📅  最后修改于: 2023-12-03 15:39:20.081000             🧑  作者: Mango

将给定数转换为回文数所要减去的最小数

当我们需要将一个数转换为回文数时,可能需要进行一些减法操作。那么如何确定要减去的最小数呢?下面介绍两种不同的方法。

方法一:从中心开始构造回文数

回文数以中心对称,因此我们可以从中心开始构造回文数。具体来说,假设给定数为 $num$,我们从它的中间位置($len = (num.length + 1) / 2$)开始,向左右两边扩展,每次将左右两边的数设为相等的。

如果新构造的回文数大于原数,那么我们就可以直接用新回文数减去原数,得到要减去的最小数。否则,我们需要在中心位置将两个数之和加 $1$,然后再进行扩展,直到构造一组大于原数的回文数。

def min_subtract(num: str) -> int:
    n = len(num)
    left = num[: (n + 1) // 2]
    right = left[::-1]
    palindrome = left + right[n // 2:]
    if int(palindrome) > int(num):
        return int(palindrome) - int(num)
    i = (n - 1) // 2
    carry = 1
    while i >= 0:
        cur = int(left[i]) + carry
        carry = cur // 10
        left = left[:i] + str(cur % 10) + left[i + 1 :]
        i -= 1
    right = left[::-1]
    return int(left + right[n // 2:]) - int(num)

以上是 Python 代码,对于其他语言,只需要更改变量名等细节即可。

方法二:从两端向中心扫描

除了从中心开始构造回文数之外,我们还可以从两端向中心扫描。具体来说,我们将给定数中间位置的数之间的数差的一半设为 $k$,然后从左右两端开始扫描,每次将左右两端的数调整为相等的,并统计调整的差值。如果扫描到中间位置仍没有构造出回文数,那么我们就在中间位置将两个数之和加 $1$,然后再向两端扩展,直到构造一组大于原数的回文数。

def min_subtract(num: str) -> int:
    n = len(num)
    mid = n // 2
    k = int(num[: mid]) - int(num[mid + (n % 2) :][::-1])
    i, j = mid, mid + (n % 2)
    diff = 0
    while i > 0:
        if num[i - 1] != num[j]:
            diff += 1
        i -= 1
        j += 1
    if diff == 0 and k >= 0:
        return k
    carry = 1
    i, j = mid - 1, mid + (n % 2)
    while i > 0:
        cur = int(num[i - 1]) + carry
        carry = cur // 10
        num = num[:i - 1] + str(cur % 10) + num[i:]
        num = num[:j] + str(cur % 10) + num[j + 1 :]
        diff += 2
        if num[i - 1] == num[j]:
            break
        i -= 1
        j += 1
    k += carry
    if diff == 0 and k > 0:
        return k
    i, j = mid - 1, mid + (n % 2)
    while i >= 0:
        cur = int(num[i]) + k
        k = cur // 10
        num = num[:i] + str(cur % 10) + num[i + 1 :]
        num = num[:j] + str(cur % 10) + num[j + 1 :]
        if k == 0:
            break
        i -= 1
        j += 1
    return int(num) - int(num[::-1])

以上是 Python 代码,同样适用于其他语言。

总结一下,给定数转换为回文数所要减去的最小数可以通过两种方法实现,一种是从中心开始构造回文数,一种是从两端向中心扫描。这两种方法的时间复杂度都是 $O(n)$,其中 $n$ 是给定数的位数。