统计字数问题

文章内就不再贴题目了,有需要大家可以直接去OJ上查看—统计字数问题


1. 算法描述

    本题目采用了排列组合的思想。分别计算每个数字在每一位上出现的次数,累加之后,即为最后的结果。
    需要特别注意的是,我们直接用排列组合直接计算,但是并没有把0 和其他数字分开来算,
    所以这样计算出来的结果就是把前导0 也一起算进去了,所以输出结果前应该减掉所有前导0。
    文字说明不够直观,下面我举个栗子来帮助大家理解这个算法

栗子

page:25634

位次 该位上数字 0-9 共同出现的次数 小于该位上数字的数额外加的值 等于该位上的数字的数额外加的值
个位 4 2563 * 1 +1 +1
十位 3 256 * 10 +10 +4
百位 6 25 * 100 +100 +34
千位 5 2 * 1000 +1000 +634
万位 2 0 * 10000 +10000 +5634

相信大家可以从表格中找到规律,想要动手实现了吧!但是别着急,现在还没有减去前导0 ,减完以后才能得到正确结果.
下面是前导0 出现次数的规律
仍以 25634为例
范围 前导0个数
10000+ 0
01000 ~ 09999 9000 * 1
00100 ~ 00999 900 * 2
00010 ~ 00099 90 * 3
00001 ~ 00009 9 * 4
00000 1 * 5


相信规律并不难找到,就不再啰嗦了。


2. 代码实现

import java.io.IOException;
import java.util.Scanner;

/**
 * Created by chen_swe on 3/12/16.
 */

public class Main {

    /**
     * 计算并累加第[lg(base) - 1] 位(从右向左)各个数字出现的次数
     *
     * @param page 总页数
     * @param base 基数,用来确定当前计算的是哪一位。
     * @param num  整形数组,用来存放各个数字出现的次数。
     */
    public static void handle(final int page, int base, int[] num) {
        int s = page / (base * 10);
        int l = page % (base * 10);
        int special = l / base;
        l %= base;
        for (int i = 0; i < 10; ++i) {
            num[i] += s * base;
            if (i < special)
                num[i] += base;
            if (i == special)
                num[i] += l + 1;
        }
    }

    /**
     * 减去前导0的个数
     *
     * @param page 总页数
     * @param num  整形数组,用来存放各个数字出现的次数。
     */
    public static void DealWithZero(int page, int[] num) {
        int len = String.valueOf(page).length();
        int tmp = 9 * (int) Math.pow(10, len - 2);
        int number = 1;
        while (tmp != 0) {
            num[0] -= tmp * number;
            tmp /= 10;
            ++number;
        }
        num[0] -= len;
    }

    public static void main(String[] args) throws IOException {
        Scanner cin =new Scanner(System.in);
        final int Page = cin.nextInt();

        int[] num = new int[10];

        int base = 1;
        while (true) {
            handle(Page, base, num);
            base *= 10;
            if (Page / base == 0)
                break;
        }
        DealWithZero(Page, num);

        for (int i : num)
            System.out.println(i);
    }
}

3. 算法分析

时间复杂度 lg(n)

你可能感兴趣的:(ACM)