📅  最后修改于: 2023-12-03 15:27:58.388000             🧑  作者: Mango
本篇文章介绍如何编写一个函数,计算不超过N的数字中,至少包含一个重复的数字的数字个数。例如,对于N=20,答案是9,因为从1到20中,有9个数至少包含一个重复的数字。
本题可以通过枚举所有数字,然后检查每个数字是否至少包含一个重复的数字来解决。但是这种解法的时间复杂度是O(NlogN),因为每个数字的位数最多是logN,我们需要对每个数字进行O(logN)时间的检查。本文介绍的是一种时间复杂度为O(logN)的解法。
我们可以先考虑如何计算1到N之间,有多少个数字不包含重复的数字。
假设有一个长度为len的数字N,我们分别考虑数字的每一位。对于每一位,我们可以用高位和低位的方式把N分成两个部分:
假设当前位的数字是x,那么有以下三种情况:
最终的答案就是将1到N的所有数字的贡献相加。具体实现可以用递归的方式按位计算。
当然,如果我们要计算至少包含一个重复的数字的数字个数,只需要使用总数减去不包含任何重复数字的数字个数即可。
下面是用Python实现的具体代码片段。需要注意的是,代码中使用的是递归方式按位计算,而不是循环方式。这是因为循环方式需要手动计算出每一位的值,而递归方式则便于直接计算当前位的贡献,从而简化了代码。同时,为了提高效率,代码中使用了记忆化(即缓存计算结果)的方式。
class Solution:
def countNumbersWithDup(self, n: int) -> int:
self.cache = {}
return n - self.countNumbersWithoutDup(n)
def countNumbersWithoutDup(self, n: int) -> int:
if n == 0:
return 0
if n < 10:
return n
if n in self.cache:
return self.cache[n]
high = int(str(n)[0])
low = int(str(n)[1:])
len_high = len(str(high))
len_low = len(str(low))
res = 0
# 计算高位中没有数字的情况
res += 9 * self.countNumbersWithoutDup(10 ** (len(n) - 1) - 1)
# 计算高位中有数字的情况
if high == 1:
res += 1 * (low + 1) + 9 * (self.countNumbersWithoutDup(10 ** (len(n) - 2) - 1))
elif high >= 2:
res += 10 * self.countNumbersWithoutDup(10 ** (len(n) - 2) - 1)
# 记录计算结果
self.cache[n] = res
return res
本文介绍了一种计算不超过N的数字中至少包含一个重复的数字的数字个数的方法。使用该方法可以在O(logN)的时间复杂度内解决该问题,比暴力枚举的O(NlogN)时间复杂度更快。同时,本文还介绍了实现思路和具体代码,希望可以帮助读者理解和实现该算法。