剑指offer面试题32从1到n整数中1出现的次数,找数学规律

/*
从1到n的n个数字 十进制表示 1出现的次数 肯定是数学题找规律呗
比如输入数字是21345 分而治之
1-1345 1346-21345
 先求第二段 万位是 一共1w个
 然后再分称1346-11345 11346-21345 每段的四个数字中 其中一个是1 其余10^3所以一共两千
 就这么分
 这个代码 理解的将就吧。。。反正就是把数字拆分开求
 又看了两便理解了。 书上有写错的地方 第一次在这本书发现错
*/
#include<cstring>
#include<iostream>
#include<string>
#include<cstdio>
#include<cstdlib>
#include<cmath>
using namespace std;

int NumberOf1(const char * str)
{
    if(!str || *str<'0' || *str>'9' || *str=='\0')
    return 0;
    int first=*str-'0';
    unsigned int len=static_cast<unsigned int>(strlen(str));
    if(len==1 && first==0)
    return 0;
    if(len==1 && first>0)
    return 1;
    int numFirstDigit=0;
    if(first>1)
        numFirstDigit=(int)pow((double)10,(double)len-1);
    else if(first==1)
        numFirstDigit=atoi(str+1)+1;//atoi函数竟然在stdlib里面!!!!
    //这里关于为什么要乘len-1理解了半天 书前面写错了,因为在除了最高位外任意一位选择1一个 设为一 所以成
    int numOtherDigits=first*(len-1)*(int)pow((double)10,(double)(len-2));
    int numRecursive=NumberOf1(str+1);
    return numFirstDigit+numOtherDigits+numRecursive;
}

int NumberOf1Between1AndN(int n)
{
    if(n<=0)
    return 0;
    char str[50];
    sprintf(str,"%d",n);
    return NumberOf1(str);
}
int main()
{
    int n;
    while(scanf("%d",&n)!=EOF)
    {
        cout<<NumberOf1Between1AndN(n)<<endl;
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值