剑指Offer——面试题31:整数中1出现的次数

18 篇文章 0 订阅
15 篇文章 0 订阅

整数中1出现的次数(从1到n整数中1出现的次数)


题目:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

输入:13

输出:6

思路:举一个例子来分析,就比较清晰了,比如1~2573中5出现的次数,我们从个位、十位然后依次分析。
对于2573的个位中会出现多少个5,主要看它前面有多少数字,即2573 / 10 = 257个,那么就会出现257个5,因为从0开始,0~256,对于2573由于个位数小于5,所以只有257个
对于十位来说,因为它前面有2573 / 100 = 25个,而且每个十位的5,会有50~59这10个,所以总的来说,十位的5就是 2573 / 100 * 10 = 250个5,又因为7 > 5,所以 2550~2559,这里还有10个没算,于是就是 (2573 / 100 + 1)* 10,十位有260个5
对于百位来说,因为它前面有 2573 / 1000 = 2个,而且每个百位的5,会有500~599这100个,所以,百位的5就是 2573 / 1000 * 100 = 200个,又因5 == 5,所以对于2573来说,还有2500~2573这74个5,即(2573 / 1000 * 100) + (2573 % 100 + 1)
对于千位来说,它前面没有值,即2573 / 10000 = 0。而且千位是2 < 5,所以千位没有5
总共就是 257 + 260 + 274 个5,所以可以看出每一位即和前面有关系,又和后面有关系,前面有n个数,就是n * pow(10, 该位(个位是0,依次类推))。后面的话主要看该位数字是否大于想累计的数字,如果是就多加 1 * pow(10, 该位(个位是0,依次类推)),如果相等,就看该位后面有多少数,比如有m,就再加个(m+1),因为从0开始计数。如果小于,就不用做任何操作

下面代码中currentNumber表示1~n的整数中某个数字出现的次数,比如currentNumber=5,就是1~n中5出现的次数。

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        int currentSum = 0;
        int bitNum = 0;
        int number = n;
        int currentNumber = 1;
        while (number > 0) {
            int num = number % 10;
            currentSum += (number / 10) * pow(10, bitNum);
            if (num > currentNumber) {
                currentSum += pow(10, bitNum);
            }
            else if (num == currentNumber) {
                int temp = n % (int)pow(10, bitNum) + 1;
                currentSum += temp;
            }
            number = number / 10;
            bitNum++;
        }
        return currentSum;
    }
};
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值