【剑指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.代码实例
暴力迭代
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 };
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 };