问题:给定一个数N求从1到N的这N个数中0,1,2,3,4,5,6,7,8,9这10个数字出现的次数。注意,所有的数字没有前导的0。 如6要写成6,而不是 006 ,06这种形式
思路1:也就是最简单最容易实现的做法,但是当n很大的时候,运行时间会变得十分长
import java.util.Scanner;
public class CountPage {
private static Scanner scanner;
public static void main(String[] args) {
scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int j;
int pageNum[] = new int[10];// 存放0--9的个数
for (int i = 1; i <= n; i++) {
int k = i;
while (k != 0) {
j = k % 10;
k = k / 10;
pageNum[j]++;
}
}
for(int i = 0;i< 10;i++)
{
System.out.println(i+"--"+pageNum[i]);
}
}
}
}
思路2:这个思路是来自《编程之美》的
假设有一个5位数N=ABCDE,我们现在来考虑百位上出现2的次数,即:从0到ABCDE的数中,有多少个数的百位上是2。分析完它,就可以用同样的方法去计算个位,十位,千位,万位等各个位上出现2的次数。
第一种情况:当百位上的数C小于2时:
1)当百位c为0时,比如说12013,0到12013中哪些数的百位会出现2?我们从小的数起, 200~299, 1200~1299, 2200~2299, … , 11200~11299, 也就是固定低3位为200~299,然后高位依次从0到11,共12个。再往下12200~12299 已经大于12013,因此不再往下。所以,当百位为0时,百位出现2的次数只由更高位决定,等于更高位数字(12)x当前位数(100)=1200个。
2)当百位C为1时,比如说12113。分析同上,并且和上面的情况一模一样。最大也只能到11200~11299,所以百位出现2的次数也是1200个。
上面两步综合起来,可以得到以下结论:
—>当某一位的数字小于2时,那么该位出现2的次数为:更高位数字x当前位数
第二种情况:当百位上的数C等于2时:
当百位C为2时,比如说12213。那么,我们还是有200~299, 1200~1299, 2200~2299, … , 11200~11299这1200个数,他们的百位为2。但同时,还有一部分12200~12213,共14个(低位数字+1)。所以,当百位数字为2时,百位出现2的次数既受高位影响也受低位影响,结论如下:
—>当某一位的数字等于2时,那么该位出现2的次数为:更高位数字x当前位数+低位数字+1
第三种情况:当百位上的数C大于2时:
当百位C大于2时,比如说12313,那么固定低3位为200~299,高位依次可以从0到12,这一次就把12200~12299也包含了,同时也没低位什么事情。因此出现2的次数是: (更高位数字+1)x当前位数。结论如下:
—>当某一位的数字大于2时,那么该位出现2的次数为:(更高位数字+1)x当前位数
通过上述分析,我们可以得到以下规律:
(1)当某一位的数字小于i时,那么该位出现i的次数为:更高位数字x当前位数
(2)当某一位的数字等于i时,那么该位出现i的次数为:更高位数字x当前位数+低位数字+1
(3)当某一位的数字大于i时,那么该位出现i的次数为:(更高位数字+1)x当前位数
下面使用java实现该算法:
import java.util.Scanner;
public class CountPagePro {
private static Scanner scanner;
public static void main(String[] args) {
scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int n = scanner.nextInt();
int[] pageNum = new int[10];
int a = 1;
int zero = 0;
int place = 0;// 位数
while (n / a != 0) {
int lowPo = a - (a / n) * n;
int curre = (a / (n)) % 10;
int highPo = a / (n * 10);
place++;
for (int i = 0; i < 10; i++) {
if (i < curre) {
pageNum[i] += (highPo + 1) * n;
} else if (i == curre) {
pageNum[i] += (highPo) * n;
pageNum[i] += (lowPo + 1);
} else {
pageNum[i] += (highPo) * n;
}
}
n = n * 10;
}
int t = 1;
while (t <= place) {
n = n / 10;
zero += t * (n - 1 - n / 10 + 1);
t++;
}
pageNum[0] = pageNum[0] - zero;
for (int i : pageNum) {
System.out.println(i + "--" + pageNum[i]);
}
}
}
}