开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 11 天,点击查看活动详情
Day38 2023/02/13
难度:中等
题目
输入一个整数 n ,求 1~n 这 n 个整数的十进制表示中 1 出现的次数
例如, 1~13 中包含 1 的数字有 1 、 10 、 11 、 12 、 13 因此共出现 6 次
注意:11 这种情况算两次
数据范围: 1≤n≤30000
进阶:空间复杂度 O(1) ,时间复杂度 O(lognn)
示例
输入:13
返回值:6
说明:1-13中包含1的数字有1, 10, 11, 12, 13, 其中11算两次
思路
我们看到题目要求 “输入一个整数 n ,求1~n这n个整数的十进制表示中1出现的次数”。其实就是求从1-n这n个数中,每一个数的计数位上出现的1的个数的总和,所以最简单的方法就是暴力解法,直接从1-n开始遍历,对每个数进行数位的拆解,然后统计1的个数就ok 了。
具体步骤:
- 从1-n进行遍历,然后对每个数字进行数为的拆解。
- 如果该计数位等于1,结果就+1,否则继续循环。
关键点
- 数位的拆解是通过模运算和除法实现的。
算法实现
c++代码实现-暴力解法
class Solution {
public:
int NumberOf1Between1AndN_Solution(int n) {
int num = 0; //统计1出现次数
for (int i = 1; i <= n; ++i) {
if (i % 10 == 1) { //拆解计数位
++num; //等于1,则结果加1
}
int a = i / 10; //去掉最后一位
for (; a > 0; a = a / 10) {
if (a % 10 == 1) {
++num;
}
}
}
return num; //最后返回结果
}
};
- 时间复杂度 --- 当数据比较大的时候,嵌套双层循环几乎每一层都循环n次,其中n为输入的整数
- 空间复杂度 --- 没有额外的辅助空间
总结
-针对本题使用暴力解法是最好理解的,但是当n取值特别大的时候,时间复杂度较高。其实本题还有用数学相关的知识点去解题,并获得更低的时间复杂度。