小C的好数
问题描述
小C对“好数”非常感兴趣,她定义一个不含前导零的正整数为“好数”,如果它的所有数位最多包含两种不同的数字。例如,数字 23,2323,9,111,和 101 都是好数。现在小C想知道,从1到nn之间有多少个好数。
例如:当n=110时,所有的1位数、2位数,以及一些3位数(如 100, 101)都是好数,一共有102个。
测试样例
样例1:
输入:
n = 110
输出:102
样例2:
输入:
n = 1000
输出:352
样例3:
输入:
n = 1
输出:1
解题思路
这道题其实不需要用到复杂的算法,遍历每一个数,判断它是否是好数即可。具体的实现步骤如下:
- 从 1 到 n,逐一遍历每个数字。
- 将数字转换为字符串,利用集合来判断该数字的数位包含多少种不同的数字。
- 如果集合的大小小于等于2,则说明这是一个好数,将计数器加一。
- 最后输出计数器的值。
关键点:
- 使用集合
set来去重数位,避免重复计算相同的数字。 - 对于较大的数字,计算时可能会有性能问题,考虑到数字的位数增大,检查每个数字的位数会稍显繁琐。
Python代码
def solution(n: int) -> int:
# write code here
count = 0
for i in range(1,n+1):
# 将数字转换为字符串形式,方便提取各个位数
num = str(i)
same = set(num)
if len(same) <= 2:
count += 1
return count
if __name__ == '__main__':
print(solution(110) == 102)
print(solution(1000) == 352)
print(solution(1) == 1)
print(solution(890000) == 4375)
代码解释
-
solution(n):这个函数用于计算从 1 到 n 之间“好数”的数量。- 使用一个
for循环遍历每个数字,从 1 到 n。 - 对于每个数字,首先将其转化为字符串形式,然后利用 Python 的集合
set来去重,从而得到该数字包含的不同数字的个数。 - 如果不同的数字个数小于等于 2,则说明这是一个“好数”,我们将计数器
count加 1。
- 使用一个
-
set(num):这里将数字num转换为字符串,并传入set中。set会自动去除重复的元素,因此它的大小就代表了数字中不同的数字个数。 -
最终返回
count:最终返回符合条件的“好数”的总数。
小缺点(思考):虽然代码的逻辑很清晰易懂,但在最坏情况下,时间复杂度为 O(n * d),其中 n 是输入的范围,d 是数字的位数。在最坏的情况下,d 约为 log(n),因为 n 越大,其位数也越多。因此,总体的时间复杂度是比较高的。 对于较小的 n,比如测试用例中的 110 或 1000,以上代码的性能完全可以接受。但是当 n 非常大时(例如数百万甚至上亿),代码的效率就会受到影响。这时,需要更加优化的算法来解决。