求1~n中0~9出現的次數
阿新 • • 發佈:2019-02-19
題目來至牛客網:頁碼統計
牛牛新買了一本演算法書,演算法書一共有n頁,頁碼從1到n。牛牛於是想了一個演算法題目:在這本演算法書頁碼中0~9每個數字分別出現了多少次?
輸入描述:輸入包括一個整數n(1 ≤ n ≤ 1,000,000,000)
輸出描述:
輸出包括一行10個整數,即0~9這些數字在頁碼中出現的次數,以空格分隔。行末無空格。
示例1
輸入999
輸出189 300 300 300 300 300 300 300 300 300
解法一
暴力破解
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
int res[] = new int[10];
for (int i = 1; i <=n; i++) {
count(res, i);
}
for (int i = 0; i < 10; i++) {
if (i != 0) {
System.out.print(" ");
}
System.out .print(res[i]);
}
}
//依次每一位求解:因為一個數i的時間複雜度為log(n),有n個數,所以總體時間複雜度是:nlog(n)。
public static void count(int res[], int n) {
//雖然簡單明瞭,但是複雜度太高
while (n != 0) {
res[n % 10]++;
n /= 10;
}
}
解法二
數字規律
拿123舉例,假設需要求1出現的個數,我們可以計算每一位上出現的個數。假設1出現在個位時數的格式是XX1 ,前面的XX能組成的個數就是1在個位時出現的次數。XX可以組成00~12共13個數。所以1在個位出現13次。當1在十位時,X1X,則可以組成(0~1)*(0~9)種,為什麼是0~9呢?因為十位為1時能組成的最大數是119,小於123所以個位可以是0~9。如果我們是求2的次數的話就需要另外判斷了,因為格式為12X能組成的數最大是123,不能是124~129,所以,只需要判斷一下當前位的數和需要求出現次數的數之間的關係即可。
程式碼如下:
/**
** num:代表題目中的n ,target:需要統計的數
**/
public static int getCount(int num, int target) {
//表示當前的位數(個位、十位。。。)
int base = 1;
//結果
int sum = 0;
int n = num;
while (n != 0) {
//以123為例,當1在個位時sum+= 1*12,並沒有加13是因為我們還沒有判斷當前位的數cur跟要求的數的關係。
sum += base * (n / 10);
//cur當前位的數如123中個位的數是3
int cur = n % 10;
if (cur == target) {
//當cur等於target,比如123,處於十位時求2出現的次數,因為只能有120~123四種情況所以,對應sum += num % base + 1
sum += num % base + 1;
} else if (cur > target) {
//當cur大於target,比如123,處於個位時求1出現的次數,需要加上12開頭的情況,所以sum += 1 * base。
sum += 1 * base;
}else if(cur<target){
//當cur小於target,比如123,處於個位時求5出現的次數,這是125是不成立的。
}
base *= 10;
n = n / 10;
}
return sum;
}
上述程式碼只能處理1~9的情況,當求0出現的次數時需要額外考慮,比如00X和0X0以及0XX都是0,這顯然不在題目的考慮範圍之類,所以,只需要將這種情況去掉即可:
程式碼如下:
public static int getCount0(int num) {
int base = 1;
int sum = 0;
int n = num;
while (n != 0) {
//區別在於這一行程式碼,減掉了1
sum += base * (n / 10 - 1);
int cur = n % 10;
if (cur == 0) {
sum += num % base + 1;
} else if (cur > 0) {
sum += base;
}
base *= 10;
n = n / 10;
}
return sum;
}
所以,牛客課網題目的答案如下:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner cin = new Scanner(System.in);
int n = cin.nextInt();
int res[] = new int[10];
res[0] = getCount0(n);
for (int i = 1; i < 10; i++) {
res[i] = getCount(n, i);
}
for (int i = 0; i < 10; i++) {
if(i!=0){
System.out.print(" ");
}
System.out.print(res[i]);
}
}
public static int getCount(int num, int target) {
int base = 1;
int sum = 0;
int n = num;
while (n != 0) {
sum += base * (n / 10);
int cur = n % 10;
if (cur == target) {
sum += num % base + 1;
} else if (cur > target) {
sum += base;
}
base *= 10;
n = n / 10;
}
return sum;
}
public static int getCount0(int num) {
int base = 1;
int sum = 0;
int n = num;
while (n != 0) {
sum += base * (n / 10 -1);
int cur = n % 10;
if (cur == 0) {
sum += num % base + 1;
}
else if (cur > 0) {
sum += base;
}
base *= 10;
n = n / 10;
}
return sum;
}
}
當然,也可以參考這篇部落格:經典的數1問題