思路:转换为每位出现1的次数 f(abcde) = f(a) + f(b) + f(c) + f(d) + f(e) f(e) = 个位出现1的次数。
先解释几个变量
iFactor:当前位置的十进制表示,如果当前位为个位,那么iFactor为1,当前位为十位,那么iFactor为10.....
iLowerNumber:比当前位置低的数字,如123,若当前位置为十位(2),那么它的iLowerNumber就是3....
iCurrentNumber:当前位置的数字。
iHigherNumber:比当前位置高的数字,如123,若当前位置为十位(2),那么它的iHigherNumber就是1....
算法:
每个位置出现1的次数又有三种情况:
1.该位置数字为0, result= iHigherNumber * iFactor;
2.该位置数字为1, result=iHigherNumber * iFactor + iLowerNumber +1;
3.给位置数字大于1,result= (iHigherNumber + 1) * iFactor;
大家可以自己举例测试上述公式,然后用数学归纳法进行总结,源码如下:
package cn.gt.algori;
/**
* 给定一个正整数N,统计从1到N的整数中,出现“1”的个数
* @author gengtao
*
*/
public class train0801_2 {
public static void main(String[] args) {
long number = 123;
long start = System.currentTimeMillis();
System.out.println("总共出现1的个数为:"+Sum1s(number));
long end = System.currentTimeMillis();
System.out.println("耗时"+(end-start)+"毫秒");
}
public static long Sum1s(long number){
long iFactor = 1; //获取高位的变量
long iLowerNumber = 0;
int iCurrentNumber = 0;
long iHigherNumber = 0;
long iCount = 0;
int i = 1;//计数第几位
while((number / iFactor) != 0){
iLowerNumber = number - (number / iFactor) * iFactor;
iCurrentNumber = (int) ((number / iFactor) % 10);
iHigherNumber = number / (iFactor * 10);
long temp = 0;
switch(iCurrentNumber){
case 0:
temp = iHigherNumber * iFactor;
break;
case 1:
temp = iHigherNumber * iFactor + iLowerNumber +1;
break;
default:
temp = (iHigherNumber + 1) * iFactor;
break;
}
System.out.println("倒数第 "+i+" 位出现1的个数为:"+temp);
iCount += temp;
iFactor *= 10;
i++;
}
return iCount;
}
}
结果如下:
倒数第 1 位出现1的个数为:13
倒数第 2 位出现1的个数为:20
倒数第 3 位出现1的个数为:24
总共出现1的个数为:57
耗时0毫秒