【剑指offer】71. 整数中1出现的次数(从1到n整数中1出现的次数)

总目录:

算法之旅导航目录

 

1.问题描述

 输入一个整数 n ,求 1~n 这 n 个整数的十进制表示中 1 出现的次数
例如, 1~13 中包含 1 的数字有 1 、 10 、 11 、 12 、 13 因此共出现 6 次

注意:11 这种情况算两次
数据范围: 1≤n≤30000
进阶:空间复杂度 O(1),时间复杂度 O(logn)

 

2.问题分析

统计某个整数中某个数字字符出现的个数,是一类问题,并不局限于统计字符1还是字符2。

暴力法

移位、取余来统计的方法肯定能做,只是很慢。

DP动态规划

n位的数字,f(n)=f(n-1)+a(n),而a(n)的设计是这里最精彩的地方。

关于a(n)的设计,直接参考大牛的解析:leetcode上的解答

 
3.代码实例

 暴力迭代

 1 class Solution {
 2   public:
 3     int getOneCount(int tgtVal) {
 4         int ret = 0;
 5         while (tgtVal > 0) {
 6             //末位是否为1
 7             if ((tgtVal % 10) == 1) {
 8                 ret++;
 9             }
10 
11             tgtVal = tgtVal / 10;
12         }
13 
14         return ret;
15     }
16 
17     int NumberOf1Between1AndN_Solution(int n) {
18         int ret = 0;
19         for (int i = 0; i <= n; i++) {
20             ret += getOneCount(i);
21         }
22 
23         return ret;
24     }
25 };
View Code

 DP动态规划

 1 class Solution {
 2   public:
 3 
 4     int NumberOf1Between1AndN_Solution(int n) {
 5         int ret = 0;
 6 
 7         int high = n / 10, cur = n % 10, low = 0, digit = 1;
 8         while (high != 0 || cur != 0) {
 9             if (cur == 0) ret += (high * digit);
10             if (cur == 1) ret += (high * digit + low + 1);
11             if (cur > 1) ret += (high + 1) * digit;
12 
13             //刷新数值
14             low = cur * digit + low;//加上高一位的数据
15             cur = high % 10;//取high的最低位
16             high /= 10;//右移1个
17             digit *= 10;//左移一个
18         }
19 
20         return ret;
21     }
22 };

 

posted @ 2022-12-06 13:52  啊原来是这样呀  阅读(53)  评论(0编辑  收藏  举报