1.题目
求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。
2.实现思路
2.1 思路一
累计1-n中每一个数中1出现的次数。将这个数中的每一位依次取出来判断是否为1,
缺点:实现效率太低。
代码实现
public class NumberOf1Between1AndN_Solution2 {
public static int numberOf1Between1AndN_Solution(int n) {
int count=0;
for (int i=0;i<=n;i++){
count+=numberOfOne(i);
}
return count;
}
private static int numberOfOne(int i) {
int base=1;
int bit=0;
int count=0;
while(i/base!=0){
bit=(i/base)%10;
if(bit==1){
count++;
}
base=base*10;
}
return count;
}
@Test
public void test(){
int n=12;
int result=numberOf1Between1AndN_Solution(n);
System.out.println(result);
}
}
2.2 思路二:
我们从一个5位的数字讲起,先考虑其百位(即base=100)为1的情况。分3种情况讨论:
百位数字>=2 example: 31256 当其百位为>=2时,有以下这些情况满足(为方便起见,计312为high,56为low):
100 ~ 199
1100 ~ 1199
.....
31100 ~ 31199
余下的都不满足!
因此,百位>=2的5位数字,其百位为1的情况有(high/10+1)*100个数字 (high/10+1)=>对应于 0 ~ 31,且每一个数字,对应范围是100个数(末尾0-99)
百位数字 ==1 example: 31156 当其百位为1时,有以下这些情况满足:
100 ~ 199
1100 ~ 1199
......
30100 ~ 30199
31100 ~ 31156
因此,百位为1的5位数字,共有(high/10)*100+(low+1)
百位数字 ==0 example: 31056 当其百位为0时,有以下这些情况满足:
100 ~ 199
1100 ~ 1199
30100 ~ 30199
其余都不满足
因此,百位数为0的5位数字,共有(high/10)*100个数字满足要求
参考博客:https://www.cnblogs.com/xuanxufeng/p/6854105.html
代码实现
public class NumberOf1Between1AndN_Solution {
public static int numberOf1Between1AndN_Solution(int n){
if(n<0){
return 0;
}
int base=1;
int current=1;
int high;
int low;
int count=0;
while((n/base)!=0){
current=(n/base)%10; //定义指针p当前指向的位
high=n/(base*10); //高位数据(p之前的数据)
low=n-(n/base)*base; //低位数据(p之后的数据)
if(current>1){
count+=(high+1)*base;
}else if(current==1){
count+=high*base+(low+1);
}else{
count+=high*base;
}
base=base*10;
}
return count;
}
@Test
public void test(){
int n=12;
int result=numberOf1Between1AndN_Solution(n);
System.out.println(result);
}
}