从0开始到N有多少个1

        由于平时自己专心在搞项目,对于算法之类的没有花太多心思。毕业临近,为了找工作,开始在leetcode上刷题。刚刚在做Number of Digit One 并百度了一下网上的解法,发现自己的解法跟别人的不太一样,所以拿出来跟大家分享下。


一、题目翻译过来大概是这么个意思: 给定一个十进制正整数N,写下从1开始,到N的所有整数,然后数一下其中出现的所有“1”的个数。

1.解法1,参照剑指offer中面试题32.

2.解法2.参照博客链接:http://blog.csdn.net/zcsylj/article/details/6393315

3.我的解法.


二、算法思路:

a.首先将一个数拆成最高位基数幂以下部分+最高位基数幂以上部分的形式,如323拆成0~300和300~323

b.要计算N中1的个数,大致分为3步:1.求取高位中1出现的次数,若最高位为1,则最高位1的重复次数为去掉最高位数加1,假设N=123,则最高位1的重复次数为23+1=24;若最高位不为1,则最高位出现次数为最高位基数幂,假设N=323,则最高位1的重复次数为100;2.求取最高位非1部分对个数1的影响,假设N=323,则可以拆成求3个0~99区间中的个数和,至于0~99可以使用排列组合很容易计算得到;3.前面两步实现对最高位基数幂以下部分计算,对于最高位基数幂以上部分,由于最高位已经不再影响1的个数,所以可以去掉最高位部分递归求取,如对于300~323,只要求N=23部分的1个数即可。

c.递归结束条件是只剩个位数。


 三、代码实现:

   //计算0~N中1的个数
   int countDigitOne(int n) {
  //若为个位数,则结束递归
       if(n<10)
  {
if(n>=1)
return 1;
else
return 0;
  }
  //计算最高位的幂
  int base=1,len=0;
  int tmp=n;
  while(tmp=tmp/10)
  {
base*=10;
len++;
  }
  //返回最高位中影响1的重复次数和递归部分
  if((n/base)>1)
return base+countDigitOne(n%base)+(n/base)*digitOne(len);
  else
  return n-base+countDigitOne(n%base)+digitOne(len)+1;
    }

 //计算0~9...9部分中1的个数
      int digitOne(int n)
   {
  if(n==1)
  return 1;
int tmp=n-1,count=1;
while(tmp)
{
count*=10;
--tmp;
}
  return count*n;
   }


四、算法性能

    其中旁边黄色的是其他方法用C++跑的性能,可以看出来使用这种方法速度还是很快的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值