📅  最后修改于: 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$ 是给定数的位数。