剑指offer 骰子概率问题

题目 :n个骰子扔在地上,所有骰子朝上一面的点数之和为s。输入n,打印出s 的所有可能的值出现的概率。


public class T42 {
    private static final int _maxValue = 6;

    public static void printRatio(int n) {
        if (n < 1) {
            return;
        }
        int max = n * _maxValue;
        int count[][] = new int[2][max];
        for (int i = 0; i < _maxValue; i++) {
            count[0][i] = 1;
        }

        if (n == 1) {
            print(count[0], 1, 6);
            return;
        }
        int flag = calculateCount(count[0], count[1], n);
        print(count[flag], n, Math.pow(_maxValue, n));

    }
    /// 没有进行计算或者进行偶数次计算,结果在count0;否则在count1
    private static int calculateCount(int[] count0, int[] count1, int num) {
        if(count0 == null ||count1 == null || num < 0){
            return -1;
        }
        int flag = 0 ;
        if(num < 2){
            return flag ;
        }
        for (int i = 2; i <= num; i++) {
            if (flag == 0) {
                if (!probability(count0, count1, i)) {
                    return -1;
                }
            } else {
                if (!probability(count1, count0, i)) {
                    return -1;
                }
            }
            flag = 1 - flag;
        }
       return flag ;
    }

    /**
     *
     * @param lefts : 上一轮计算的结果
     * @param rights : 存储本轮计算结果
     * @param num
     * @return
     */
    private static boolean probability(int[] lefts, int[] rights, int num) {
        if (lefts == null || lefts.length < 1 || rights == null || rights.length < 1 || num < 0) {
            return false;
        }
        for (int i = 0; i < num * _maxValue; i++) {
            rights[i] = 0;
        }
        for (int i = num; i <= num * _maxValue; i++) {
            calculate(lefts, rights, i - 1);
        }
        return true;

    }

    /**
     * right[n] = left[n-1] + left[n-2] + left[n-3] + left[n-4] + left[n-5] + left[n-6]
     * 注意 数组边界的处理
     * @param lefts
     * @param rights
     * @param cursor
     */
    private static void calculate(int[] lefts, int[] rights, int cursor) {
        if (lefts == null || rights == null || cursor < 0 || cursor >= rights.length) {
            return;
        }
        int index = cursor;
        int offSet = 1;
        while ((index - offSet >= 0) && (index - offSet < lefts.length) && offSet <= _maxValue) {
            rights[cursor] += lefts[index - offSet];
            offSet++;
        }
    }

    /**
     * 打印结果
     * @param count :最后结果
     * @param num : 骰子个数
     * @param total :总数
     */
    private static void print(int[] count, int num, double total) {
        if (count == null || count.length < 1 || total < 0) {
            return;
        }
        double ratio = 0;
        System.out.println("----骰子个数为 : " + num);
        System.out.println("----所有点数的可能有 " + total + " ");

        for (int i = 1; i <= count.length; i++) {
            System.out.print("点数:" + i + "  出现次数:" + count[i - 1]);
            ratio = count[i - 1] / total;
            System.out.printf("  概率为 :%-8.4f \n", ratio);
        }
    }

    public static void test(){
        printRatio(1);
        System.out.println("\n");


        printRatio(2);
        System.out.println("\n");


        printRatio(3);
        System.out.println("\n");

        printRatio(4);
    }

    public static void main(String args[]){
        try{
            test();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}


你可能感兴趣的:(面试&基础算法)