【剑指offer】面试题32-从1到n整数中1出现的次数

来源:互联网 发布:扬州网络电视台 编辑:程序博客网 时间:2024/06/06 00:19

题目描述:

输入一个整数N,求出1~N这N个整数的十进制表示形式中 1出现的次数。比如输入12,从1~12这12个整数中包含1的数字有:1,10,11,12,1总共出现了5 次。


题目分析:

看到这个题目,大多数人的想法或许就是:循环遍历1~N中的每一个数,然后求出每个数中1的个数,然后求和。这样做的话,需要将N个数遍历一遍,然后将每个数的每一位遍历一次,时间复杂度是比较高的(大于O(N)),所以我们依然找规律去做这个题目。
假如给定的数据是24531.
我们可以将数据的范围(1~24531)分成2部分1~4531和4532~24531.然后求出每一个范围中1的个数,将结果进行相加即可。
在4532~24531中最高位出现1的个数,一共就是10000(10000~19999)个.
如果我给定的数据是12345,最高位出现1的个也是10000吗?显然不是。而是2345+1 = 2346(10000~12345)个。
那么剩下四位中1出现的个数又该如何计算呢?2*4*10^(5-2) == 8000个。
这个范围可以再分为2个范围,4532~14531和14532~24531.对于低4位,取任意一位是1(4种取法),其余3位就有10*10*10 == 1000种可能。
在1~4531这个范围中,我们就可以继续上边的步骤(递归实现)。


实现代码:

#include<iostream>using namespace std;#include<cassert>//1~N的十进制表示中出现的次数int Power(int n){    int result = 1;    for(int i = 0; i < n; ++i)    {       result *= 10;    }    return result;}int numberOf1(const char* str){    if(*str < '0'|| *str > '9' || *str == '\0' || str == NULL)//字符串不正确,进而说明数据有误       return 0;    int length = strlen(str);    int first = *str - '0';    if(first == 0 && length == 1)//处理这种情况       return 0;    if(first > 0 && length == 1)//处理N是个位数的情况       return 1;    //假如给定的数是 24531  数字分为两部分 1~4531 和4532 ~ 24531    //1,2计算的是~ 24531中的个数    //3计算的是1~ 4531中的个数    //1.计算~19999中出现的次数    int CountFirstDigit = 0;    if(first > 1)       CountFirstDigit = Power(length-1);    if(first == 1)       CountFirstDigit = atoi(str+1)+1;    //2.计算后面位中出现的次数    int CountOtherDigits = first * (length -1) * Power(length - 2);    //3.计算~4531中出现的个数    int CountRest = numberOf1(str + 1);    return CountFirstDigit+ CountOtherDigits + CountRest;}int GetCount(int n){    if(n <= 0)       return 0;    char str[15];    _itoa(n,str,10);//将输入的数字转为字符串,为了方便编写程序    return numberOf1(str);}int main(){    int n = 0;    cin>>n;    cout<<GetCount(n)<<endl;    system("pause");    return 0;}

总结:

这里我们之所以将数字转为字符串,是为了方便表示数字,当然不转换也是可以的,只是表示起来或许比较麻烦。
整数转换成字符串的函数:char* _itoa(int n,char* string,int radix);
n表示要转换的整数,转换之后的字符串存储在string中,radix是一个整数,表示n是radix进制的整数。
当然也可以使用sprintf函数进行转换。
int sprintf(char* buffer,const char* format…);
sprintf(buffer,”%s”,n);表示n以%d的形式写进buffer中,返回值是写进去的字节数。


关于这道题目就先分析到这里~

1 0
原创粉丝点击