【题目】
给定一个整数n,返回从1到n的数字中1出现的个数。
例如:
n=5,1~n为1,2,3,4,5。那么1出现了1次,所以返回1。
n=11,1~n为1,2,3,4,5,6,7,8,9,10,11。那么1出现了4次,所以返回4。
【代码】
public static void main(String[] args) {
//方法一
System.out.println(countOneNums(5));//1
System.out.println(countOneNums(11));//4
//方法二
System.out.println(get1Nums2(5));//1
System.out.println(get1Nums2(11));//4
}
//1到n中1出现的次数
public static int countOneNums(int num){
if(num<=0){
return 0;
}
int count=0;
for(int i=1;i<=num;i++){
//依次判断1到n每个数中1的个数
count+=get1Nums(i);
}
return count;
}
private static int get1Nums(int num) {
int res=0;
while(num!=0){
if(num%10==1){//判断最低位是否为1
res++;
}
num/=10;//除去最低位
}
return res;
}
//方法二:不再依次考察每个数,而是分析1出现的规律
public static int get1Nums2(int num){
if(num<1){
return 0;
}
int len=getLenOfNum(num);
if(len==1){//num只有个位数
return 1;
}
int tmp1=powerBaseOf10(len-1);//10^(k-1)
int first=num/tmp1;//最高位
//最高位是1,则最高位上1的数量=除去最高位后剩下的数+1;否则,=10^(k-1)
int firstOneNum=first==1?num%tmp1+1:tmp1;
//其他位上1的总数量=最高位的数字*除去最高位后剩下的位数*某一位固定是1的情况下,剩下3位数自由变化(即10^(k-1))
int otherOneNum=first*(len-1)*(tmp1/10);
//n有多少位,递归函数就会被调用多少次
return firstOneNum+otherOneNum+get1Nums2(num%tmp1);
}
//10的base次方,即10^(k-1)
private static int powerBaseOf10(int base) {
return (int) Math.pow(10, base);
}
//求出n的位数
private static int getLenOfNum(int num) {
int len=0;
while(num!=0){
len++;
num/=10;
}
return len;
}