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

来源:互联网 发布:javascript的作用 编辑:程序博客网 时间:2024/05/19 02:45

题目:

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

解法一:

暴力解法:
遍历从1到n的整数,判断每个整数1的个数,再相加。时间复杂度为O(n*logn)。

int Numberof1(unsigned int n){    int ones=0;    for(unsigned int i=1;i<=n;++i)        ones+=Numberof1Core(i);    return ones;}int Numberof1Core(unsigned int n){    int  num=0;    while(n)    {        if(n%10==1)            num++;        n=n/10;    }    return num;}

解法二:

判断1在每个数字位(个位,十位..)上1出现的次数,将所有数字位上的1全部相加。

对于每个当前处理位,可分成该位的数字为0,1,或者>1的情况分析如下:
1.假设现在分析百位,若百位上的数字>1,假设数字n=321523, 则从百位分割数字可得a=n/100=3215,b=n%100=23。则我们知道当百位上的数字取1的时候,高于百位的数字可以取0~321,共322*100个数,即(a/10+1)*100。
2. 若百位上的数字=1的时候,假设数字n=321123,则从百位分割数字可得a=n/100=3211,b=n%100=23。则我们知道当百位上的数字取1的时候,高于百位的数字可以取0~321,但是需要注意的是当高位取3211的时候,低位只能取0~23,所以该数字位为1的总数为(a/10)*100+(b+1)。
3. 如百位上的数字为0的时候,假设数字为n=321023, 则从百位分割数字可得a=n/100=3210,b=n%100=23。则我们知道当百位上的数字取1的时候,高于百位的数字只能取0~320,(因为取321的时候,组成的数将超过321023)即(a/10)*100。
4. 综上,我们可以将数字为0和>1的情况合并表示为(a+8)/10*100.(当a的百位上的数大于1时,(a+8)/10相当于a/10+1,当a的百位上的数为0时,(a+8)/10相当于a/10),而当百位上的数为1的时候,还需加上b+1。

则有上面的分析,代码可得如下:

int NumberOf1Between1AndN_Solution(int n){    int ones=0;     for(long long m=1;m<=n;m*=10){         int a=n/m,b=n%m;         ones+=(a+8)/10*m+(a%10==1)*(b+1);     }     return ones; }
原创粉丝点击