#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
// 参考《剑指offer 面试题32:从1到n整数中1出现的次数 P174》
int powerOfn( int n )
{
int result = 1;
int cnt = 1;
while( cnt <= n )
{
result *= 10;
cnt++;
}
return result;
}
int numberOfOne( const char *str )
{
int result = 0;
if( NULL == str || *str < '0' || *str > '9' || '\0' == *str )
{
return result;
}
int len = strlen(str);
int first = *str - '0';
if( 1 == len && 0 == first )
{
result = 0;
return result;
}
if( 1 == len && 1 == first )
{
result = 1;
return result;
}
int number1 = 0; // 保存最高位为1的数的个数,如str="38763"时,number1的数量为: 10000 - 19999,总为10000
if( first > 1 )
{
number1 = powerOfn( len - 1 );
}
else if( 1 == first )
{
number1 = atoi( str + 1 ) + 1;
}
// str=21345
int number2 = numberOfOne( str + 1 ); // number2保存除了最高位后剩余数字
int number3 = first * ( len - 1 ) * powerOfn( len - 2 ); // 1346-21345中除了最高位为1,剩余任意数字为1的数包含1的个数的和
result = number1 + number2 + number3;
return result;
}
int numbersOf1Between1AndN( int n )
{
int result = 0;
if( n <= 0 )
{
return result;
}
char str[50];
sprintf( str, "%d", n );
result = numberOfOne(str);
return result;
}
// 这种思路是每次去掉最高位做递归,一个数字n有O(logn)位,复杂度为O(logn)
int main()
{
int ret = 0;
cout << numbersOf1Between1AndN( 21345) << endl;
return ret;
}