题目描述
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数。
/**
* 从1到n中1出现的次数,可扩展为从1到n中x出现的次数。[1<=x<=9]
* @author 过路的守望
*
*/
public class NumberOfOnes {
public static void main(String[] args) {
System.out.println(new NumberOfOnes().getNumberOfOnes(1));
}
/**
* 编程之美上给出的规律: \
* 1. 如果第i位(自右至左,从1开始标号)上的数字为0,则第i位可能出现1的次数由更高位决定(若没有高位,视高位为0),等于更高位数字X当前位数的权重10^i-1。
* 2.如果第i位上的数字为1,则第i位上可能出现1的次数不仅受更高位影响,还受低位影响(若没有低位,视低位为0),等于更高位数字X当前位数的权重10^i-1+(低位数字+1)。
* 3.如果第i位上的数字大于1,则第i位上可能出现1的次数仅由更高位决定(若没有高位,视高位为0),等于(更高位数字+1)X当前位数的权重10^i-1。
* @param n
* @return
*/
public int getNumberOfOnes(int n) {
if (n <= 0) {
return 0;
}
/**
* high 高位
* low 低位
* cur 当前位 (第 i 位)
*/
int high = n;
int curAndLow = 0;
int cur = 0;
int low = 0;
int i = 1;
int count = 0;
while (high != 0) {
high = n / (int) Math.pow(10, i);
curAndLow = n % (int) Math.pow(10, i);
cur = curAndLow / (int) Math.pow(10, i - 1);
low = curAndLow % (int) Math.pow(10, i - 1);
if (cur == 1) {
count += high * (int) Math.pow(10, i - 1) + low + 1;
} else if (cur < 1) {
count += high * (int) Math.pow(10, i - 1);
} else {
count += (high + 1) * (int) Math.pow(10, i - 1);
}
i++;
}
return count;
}
}