题目:输入一个整数n,求从1到n这n个整数的十进制表示中1出现的次数。例如输入12,从1到12这些整数中包含1的数字有1,10,11和12,1一共出现了5次。

方法1:不考虑时间效率的解法如下:

int NumberOf1Between1AndN(unsigned int n)
{
    int number=0;
    
    for(unsigned int i=1;i<=n;++i)
        number+=numberOf1(i);
    return number;
}

int NumberOf1(unsigned int n)
{
    int number=0;
    while(n)
    {
        if(n%10==1)
            number++;
        n=n/10;
    }
    
    return number;
}

方法2:从数字规律着手明显提高时间效率的解法。

int NumberOf1Between1AndN(int n)
{
    if(n<=0)
        return 0;
        
    char strN[50];
    sprintf(strN,"%d",n);
    
    return NumberOf1(strN);
}

int NumberOf1(const char* strN)
{
    if(!strN||*strN<'0'||*strN>'9'||*strN=='\0')
    return 0;
    
    int first=*strN-'0';
    unsigned int length=static_cast<unsigned int>(strlen(strN));
    
    if(length==1&&first==0)
        return 0;
        
    if(length==1&&first>0)
        return 1;
        
    int numFirstDigit=0;
    if(first>1)
        numFirstDigit=PowerBase10(length-1);
    else if(first==1)
        numFirstDigit=atoi(strN+1)+1;
        
    int numOtherDigits=first*(length-1)*PowerBase10(length-2);
    int numberRecursive=NumberOf1(strN+1);
    
    return numFirstDigit+numOtherDigits+numRecursive;
}

int PowerBase10(unsigned int n)
{
    int result=1;
    for(unsigned int i=0;i<n;i++)
        result*=10;
        
    return result;
}