有两种解法,时间复杂度不同。
java代码实现:
/** 解法一 (时间复杂度为o(n)*lgn)
*
*
* 最直观的方法,分别求得1到n中每个整数中1出现的次数。
*
*/
private static int printNumbersOfOne(int start, int end) {
int sumOfone = 0;
for(int i=start;i<=end;i++) {
sumOfone += getNumbersOfOne(i);
}
return sumOfone;
}
private static int getNumbersOfOne(int num) {
int result = 0;
//int b = 0;
while(num != 0) {
if(num%10 == 1) {
result ++;
}
num = num / 10;
}
return result ;
}
/**解法二 (时间复杂度为o(n))
*
* 针对各位上出现的1的次数做统计,如30143:
由于3>1,则个位上出现1的次数为(3014+1)*1
由于4>1,则十位上出现1的次数为(301+1)*10
由于1=1,则百位上出现1次数为(30+0)*100+(43+1)
由于0<1,则千位上出现1次数为(3+0)*1000
*
*/
private static long CountNumberOne(long num) {
if(num <=0)
return 0;
long count = 0; //1的个数
long current ; //当前位
long base = 1; //基数
long remain = 0; //当前位等于1时,后面剩余的部分数目
while(num > 0) {
current = num % 10;
num = num / 10;
if(current > 1)
count += (num + 1) * base;
else if(current == 1)
count += num * base + (remain+1) ;
else
count += num * base ;
remain += current * base ;
base = base * 10;
}
return count ;
}