给定一个十进制正整数N,写下从1开始到N的所有整数,然后数一下其中1出现的次数。
例如:
N=2,写下1,2。1只出现了1次。
1、写一个函数f(N),返回1到N之间,出现的“1”的个数,比如f(12)=5;
2、满足条件“f(N)=N”的最大的N是多少?
解法一:
从1遍历到N,计算每个数[1…N]上出现的1的次数。
public class Main {
public static void main(String[] args) {
int n = 100000000;
System.out.println(fun(n));
}
private static int fun(int n) {
int count = 0;
for (int i = 1; i <= n; i++) {
count += funExtra(i);
}
return count;
}
private static int funExtra(int n) {
int count = 0;
while (n > 0) {
count += (n % 10 == 1) ? 1 : 0;
n /= 10;
}
return count;
}
}
解法一的时间复杂度为O(N*log2(N))。
解法二:
从个位到遍历到最高位,计算每个位上面1出现的次数,同时进行累加。
例如:
N=12013
1、在个位上为3,则“1”出现的次数与前面的4位“1201”有关,出现“1”的次数为1201+1=1202次;
2、在十位上位1,则“1”出现的次数与前面的3位“121”和后面的“3”有关,出现“1”的次数为120*10+(3+1)=1204次;
3、在百位上位0,则“1”出现的次数与前面的2位“12”和后面的“13”有关,出现“1”的次数为12*100=1200次;
4、在千位上位2,则“1”出现的次数与前面的1位“1”和后面的“13”有关,出现“1”的次数为(1+1)*1000=2000次;
4、在万位上位1,则“1”出现的次数与后面的“2013”有关,出现“1”的次数为2013+1=2014次;
一共有7620个1。
其中,要注意的是必须对每个位上出现的数字分三种情况进行讨论:
1、“0”,
2、“1”,
3、“2,3,4,5,6,7,8,9”
代码如下:
public class Main {
public static void main(String[] args) {
int n = 12013;
System.out.println(fun(n));
}
private static int fun(int n) {
int mCurrent = 0;
int mUp = 0;
int mDown = 0;
int j = 1;
int count = 0;
while (n / j != 0) {
mCurrent = n / j % 10;
mUp = n / (10 * j);
mDown = n - (n / j) * j;
switch (mCurrent) {
case 0:
count += mUp * j;
break;
case 1:
count += mUp * j + mDown + 1;
break;
default:
count += (mUp + 1) * j;
break;
}
j *= 10;
System.out.println(count);
}
return count;
}
}
对于满足N=f(N)的最大N是多少。
我们如下分析:
当N<=9时,1有1个;
当N<=99时,1有20个;
当N<=999时,1有300个;
可以得出公式:f(10^n-1)=n*10^(n-1)
可以发现当n>=10时,f(10^n-1)<n*10^(n-1),当n<=9时,f(10^n-1)>n*10^(n-1)。
在10^9-1<N<10^10-1之间,可能存在N=f(N)。
最后得到N=1111111110时,成立。