1. 问题背景与需求解析
今天遇到一个有趣的编程练习题:如何高效统计从1到n的所有整数中数字9出现的总次数?这个问题看似简单,但实际暗藏玄机。比如当n=100时,数字9出现了20次(9,19,29...99),但你能快速算出n=1,000,000时的结果吗?
这类数字统计问题在实际开发中并不少见,比如:
- 分析日志文件中特定错误码出现频率
- 统计用户ID中特定数字的分布情况
- 验证数据集中数字特征的分布规律
2. 基础解法与性能分析
2.1 暴力枚举法
最直观的解法就是遍历每个数字并统计9的个数:
python复制def count_nines_naive(n):
count = 0
for num in range(1, n+1):
count += str(num).count('9')
return count
时间复杂度分析:
- 外层循环执行n次
- 每次循环需要将数字转为字符串(O(log n))
- 总复杂度为O(n log n)
当n=1,000,000时,在我的笔记本上执行约需1.2秒。虽然对小规模数据可行,但面对n=1e9这样的大数时就力不从心了。
2.2 数学规律解法
观察数字排列规律可以发现更高效的算法。以统计1-100中9的个数为例:
个位出现9的次数:
- 固定个位为9,十位可取0-9:09,19,29...99 → 共10次
十位出现9的次数:
- 固定十位为9,个位可取0-9:90,91...99 → 共10次
- 但99被重复计算,实际总数=10+10-1=19次
推广到一般情况,对于n位数,数字9在每一位出现的次数可以通过以下公式计算:
code复制count = n * 10^(n-1)
3. 优化算法实现
3.1 分位数统计法
基于上述数学规律,我们可以逐位统计9的出现次数:
python复制def count_nines_math(n):
count = 0
position = 1 # 当前处理的位置(个位=1,十位=10...)
while position <= n:
# 计算当前位的高位和低位
