求1~n中0~9出现的次数

- 日理万妓 2022-06-07 01:56 216阅读 0赞

题目来至牛客网:页码统计
牛牛新买了一本算法书,算法书一共有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

解法一

暴力破解
  1. public static void main(String[] args) {
  2. // TODO Auto-generated method stub
  3. Scanner cin = new Scanner(System.in);
  4. int n = cin.nextInt();
  5. int res[] = new int[10];
  6. for (int i = 1; i <=n; i++) {
  7. count(res, i);
  8. }
  9. for (int i = 0; i < 10; i++) {
  10. if (i != 0) {
  11. System.out.print(" ");
  12. }
  13. System.out.print(res[i]);
  14. }
  15. }
  16. //依次每一位求解:因为一个数i的时间复杂度为log(n),有n个数,所以总体时间复杂度是:nlog(n)。
  17. public static void count(int res[], int n) {
  18. //虽然简单明了,但是复杂度太高
  19. while (n != 0) {
  20. res[n % 10]++;
  21. n /= 10;
  22. }
  23. }

解法二

数字规律

拿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,所以,只需要判断一下当前位的数和需要求出现次数的数之间的关系即可。
代码如下:

  1. /**
  2. ** num:代表题目中的n ,target:需要统计的数
  3. **/
  4. public static int getCount(int num, int target) {
  5. //表示当前的位数(个位、十位。。。)
  6. int base = 1;
  7. //结果
  8. int sum = 0;
  9. int n = num;
  10. while (n != 0) {
  11. //以123为例,当1在个位时sum+= 1*12,并没有加13是因为我们还没有判断当前位的数cur跟要求的数的关系。
  12. sum += base * (n / 10);
  13. //cur当前位的数如123中个位的数是3
  14. int cur = n % 10;
  15. if (cur == target) {
  16. //当cur等于target,比如123,处于十位时求2出现的次数,因为只能有120~123四种情况所以,对应sum += num % base + 1
  17. sum += num % base + 1;
  18. } else if (cur > target) {
  19. //当cur大于target,比如123,处于个位时求1出现的次数,需要加上12开头的情况,所以sum += 1 * base。
  20. sum += 1 * base;
  21. }else if(cur<target){
  22. //当cur小于target,比如123,处于个位时求5出现的次数,这是125是不成立的。
  23. }
  24. base *= 10;
  25. n = n / 10;
  26. }
  27. return sum;
  28. }

上述代码只能处理1~9的情况,当求0出现的次数时需要额外考虑,比如00X和0X0以及0XX都是0,这显然不在题目的考虑范围之类,所以,只需要将这种情况去掉即可:
代码如下:

  1. public static int getCount0(int num) {
  2. int base = 1;
  3. int sum = 0;
  4. int n = num;
  5. while (n != 0) {
  6. //区别在于这一行代码,减掉了1
  7. sum += base * (n / 10 - 1);
  8. int cur = n % 10;
  9. if (cur == 0) {
  10. sum += num % base + 1;
  11. } else if (cur > 0) {
  12. sum += base;
  13. }
  14. base *= 10;
  15. n = n / 10;
  16. }
  17. return sum;
  18. }

所以,牛客课网题目的答案如下:

  1. import java.util.Scanner;
  2. public class Main {
  3. public static void main(String[] args) {
  4. // TODO Auto-generated method stub
  5. Scanner cin = new Scanner(System.in);
  6. int n = cin.nextInt();
  7. int res[] = new int[10];
  8. res[0] = getCount0(n);
  9. for (int i = 1; i < 10; i++) {
  10. res[i] = getCount(n, i);
  11. }
  12. for (int i = 0; i < 10; i++) {
  13. if(i!=0){
  14. System.out.print(" ");
  15. }
  16. System.out.print(res[i]);
  17. }
  18. }
  19. public static int getCount(int num, int target) {
  20. int base = 1;
  21. int sum = 0;
  22. int n = num;
  23. while (n != 0) {
  24. sum += base * (n / 10);
  25. int cur = n % 10;
  26. if (cur == target) {
  27. sum += num % base + 1;
  28. } else if (cur > target) {
  29. sum += base;
  30. }
  31. base *= 10;
  32. n = n / 10;
  33. }
  34. return sum;
  35. }
  36. public static int getCount0(int num) {
  37. int base = 1;
  38. int sum = 0;
  39. int n = num;
  40. while (n != 0) {
  41. sum += base * (n / 10 -1);
  42. int cur = n % 10;
  43. if (cur == 0) {
  44. sum += num % base + 1;
  45. }
  46. else if (cur > 0) {
  47. sum += base;
  48. }
  49. base *= 10;
  50. n = n / 10;
  51. }
  52. return sum;
  53. }
  54. }

当然,也可以参考这篇博客:经典的数1问题

发表评论

表情:
评论列表 (有 0 条评论,216人围观)

还没有评论,来说两句吧...

相关阅读

    相关 1~n0~9出现次数

    > 题目来至牛客网:[页码统计][Link 1] > 牛牛新买了一本算法书,算法书一共有n页,页码从1到n。牛牛于是想了一个算法题目:在这本算法书页码中0~9每个数字分别出