📅  最后修改于: 2023-12-03 15:27:47.118000             🧑  作者: Mango
这个问题可以分为两个部分:(1)如何生成位数不超过K个非零数字的数字;(2)如何计数该范围内的数字数量。
一种简单的方法是使用递归回溯。我们可以从第一位开始,遍历从1到9的所有数字。如果已经生成了j位数字,那么下一位数字可以是0到9中除了0以外的任意一个数字。如果当前已经生成了k个非零数字,那么下一位数字只能是0。当生成的数字的位数达到k位时,递归终止并将该数字加入到结果集中。
def generate_numbers(n: int, k: int) -> List[int]:
result = []
def dfs(num: int, count: int):
if len(str(num)) > k or count > k:
return
if num >= n:
return
result.append(num)
for i in range(0 if num else 1, 10):
non_zero = count + (i != 0)
dfs(num * 10 + i, non_zero)
dfs(0, 0)
return result
其中,参数n表示范围的上界,k表示数字中最多可以有k个非零数字。返回一个列表,其中包含所有符合要求的数字。
我们可以使用二分答案的思想得到范围内符合要求的数字数量。假设我们已经得到了所有符合要求的数字,那么数量就是所有数字中小于等于上界n的数字个数减去所有数字中小于下界0的数字个数。由于两个数字的差可能很大,我们可以通过对数字位数的差分别计算数量并相加,然后使用前缀和计算范围内的数量。
def count_numbers(n: int, k: int) -> int:
numbers = generate_numbers(n, k)
counts = [0] * (k + 1)
total_count = 0
for i in range(1, k + 1):
counts[i] = counts[i - 1] * 9 + 10 ** (i - 1)
total_count += counts[i]
def calc_count(x: int) -> int:
if x == 0:
return 0
digits = list(map(int, str(x)))
prefix_count = 0
non_zero_count = 0
for i, digit in enumerate(digits):
num_count = 0
for j in range(0 if i else 1, digit):
if non_zero_count + (j != 0) <= k:
num_count += 1
prefix_count += num_count * (counts[len(digits) - i - 1] + (non_zero_count + (digit != 0)))
if digit != 0:
prefix_count += calc_count(int(''.join(map(str, digits[i + 1:]))))
non_zero_count += 1
if non_zero_count > k:
break
return prefix_count
return calc_count(n) - calc_count(0)
其中,参数n表示范围的上界,k表示数字中最多可以有k个非零数字。返回一个整数,表示该范围内所有符合要求的数字数量。
本文介绍了如何计算范围内的数字数量,其中数字包含的位数不超过K个非零数字。我们可以使用递归回溯的方法生成所有符合要求的数字,然后使用二分答案的方法计算数量,并使用前缀和优化时间复杂度。