整数中1出现的次数(剑指Offer算法题)

题目

求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

思路

看了前人的一些思路,感觉很多都不是很清楚,博主想清楚了以后就过来试试自己写一篇博文。
首先遍历查找的效率为O(nlogn),每个数都得检查每个位是否为1,显然不是一个好办法。这道题主要要利用数字的规律进行快速计算,想法是每次计算从个位到最高位的1的个数,累加即可。那么每位1的个数如何计算呢?核心想法就是固定每一位为1,不超过当前数n的情况下其他位最多的可能组合有几种。
以123456为例,个位上1总共出现12346次,即个位的1固定,前面5位为任意数都可以,所以从0到12345共12346种可能。十位出现次数为1235*10,十位的1固定以后,前4位共1235种可能,而个位有10种可能(不必考虑重复,因为计算的是不同位上的1)。依此类推,百位上出现124 * 100个,千位上出现2 * 1000个,而万位上出现10^5个。
但是其实这边根据每位digit的不同需要分类,以数字n=123x56为例,我们探讨百位出现1的个数:
1)x=0时,共123 * 100种可能(前三位固定123时百位不能取1);
2)x=1时,共123 * 100+57种(前三位为123时,百位取1,后面两位共57种可能);
3)x>1时,共124 * 100种。

这样我们不难写出如下的代码:

class Solution {
public:
    int NumberOf1Between1AndN_Solution(int n)
    {
        int cnt = 0;
        int i, a, b, c, d;
        for (i=10; i/10<=n; i*=10){
            a = n/i;
            b = n%i;
            c = b/(i/10);
            d = b%(i/10);
            cnt += a*i/10+(c>1)*i/10+(c==1)*(d+1);
        }
        return cnt;
    }
};

大家如果有什么问题或者有其他思路欢迎和博主讨论哈~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值