题目:
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
思路1:(37ms)
从前向后一个一个的判断,累加
代码:
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
int num = 0;
if(n == 0){
return 0;
}
if(n / 10 == 0){
return 1;
}
for(int i = 1; i <= n; i++){
int temp = i;
while(temp > 0){
int b = temp % 10;
if(b == 1){
num++;
}
temp = temp / 10;
}
}
return num;
}
}
思路二:(15ms)
以214,为例:
个位上从0到9变化的次数,是21次,个位上1的总次数就是21加上最后一次(214%10是4,大于1,最后加1),21+1=22;
十位上从0到9变化的次数,是2次,十位上1的总次数就是2*10(十位上是1,说明连着10个数十位上都是1,所以乘10)加上最后4+1次(因为十位上是1,所以除了0到9变化的2次外,剩余的十位上1的次数取决于个位,当前例子就是210,211,212,213,214,5个,也就是个位数+1,);
百位上从0到9变化的次数,是0次,百位上的总次数就是0*100加上最后100次(234%1000=234,大于100,最后加100次)。
所以最后的表达式就是,n/Math.pow(10,i)+temp
其中,temp的取值有3中情况,n%(Math.pow(10,i)) == 0时,temp = 0(余数是0);
n%(Math.pow(10,i)) / Math.pow(10,i-1) == 1时,取决于前一位,比如十位是1,它的temp取决于个位,temp = n%(Math.pow(10,i)) - Math.pow(10,i-1) +1;
最后一种情况就是当前位不是1也不是0,如上例中的个位和百位的计算方式,temp = Math.pow(10,i-1)
代码:
public class Solution {
public int NumberOf1Between1AndN_Solution(int n) {
if(n == 1 || n == 0){
return n;
}
if(n / 10 == 0){
return 1;
}
int num = 0;
int a = n / 10;
int b = n % 10;
int temp = 0;//最后加的数
int i = 1;
int len = 0;
int t = n;
while(t != 0){
t= t /10;
len++;
}
while( i <= len){
if(b == 0){
temp = 0;
}
else if((int)(b / Math.pow(10,i-1)) == 1){
temp =(int)(b - Math.pow(10,i-1)+1);
}else{
temp = (int)(Math.pow(10,i-1));
}
num += a * Math.pow(10,i-1) + temp;
i++;
a = (int)(n / Math.pow(10, i));
b = (int)(n % Math.pow(10, i));
}
return num;
}
}