您的位置:首页 > 编程语言 > C语言/C++

(C++)剑指offer-31:整数中1出现的次数(时间效率)

2018-02-14 20:41 369 查看

剑指offer-31:整数中1出现的次数(从1到n整数中1出现的次数)

目录

剑指offer-31整数中1出现的次数从1到n整数中1出现的次数

目录
1题目描述

2题目解析及答案

1题目描述

求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。

ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。



2题目解析及答案

class Solution {
public:
int NumberOf1Between1AndN_Solution(int n){
int ones = 0;
for (long long m = 1; m <= n; m *= 10)
ones += (n/m + 8) / 10 * m + (n/m % 10 == 1) * (n%m + 1);
return ones;
}
};


int a = n/m, b = n%m;

注解:参考leetcode(包括求1~n的所有整数中2,3,4,5,6,7,8,9出现的所有次数)

通过使用一个位置乘子m 遍历数字的位置, m 分别为1,10,100,1000…etc.(m<=n)

对于每个位置来说,把10进制数分成两个部分

(1)比如说当m=100的时候, 把十进制数 n=3141592 分成 a=31415 和 b=92 ,以此来分析百位数为1时所有数的个数和。

m=100时,百位数的前缀为3141

当百位数大于1时,为3142*100,因为当百位数大于1时,前缀可以为0,即百位数可以从100到199,共100个数;

当百位数不大于1时,为3141*100;

如何判断百位数是否大于1?

假设百位数为x,若(x+8)/10等于1,则大于1,若(x+8)/10等于0,则小于1。

因此前缀可用(n/m + 8)/10 *m来计算(若计算2的个数,可以改为(n/m + 7)/10*m,若计算3的个数,改为(n/m + 6)/10*m,…以此类推)。

(2)再例如m=1000时,n分为a=3141和 b=592;

千位数的前缀为314,千位数不大于1,故前缀计算为314*1000;

因为千位数为1,再加b+1(0到592)。即千位数为1的所有书的个数和为314*1000+592+1;公式(n/m + 8)/10*m + b +1。

注意:只有n的第m位为1时需要计算后缀,后缀计算为 (n/m%10==1)*(b+1)

即(n/m%10==1)判断第m位是否为1,若为1,则加上(b+1),若不为1,则只计算前缀。

(若计算2的个数,可以改为(n/m%10==2)(b+1),若计算3的个数,可以改为(n/m%10==3)(b+1)…以此类推)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐