剑指Offer面试题43n个骰子的点数(动态规划),面试题44扑克牌的顺子

面试题43:n个骰子的点数(动态规划)

扔n个骰子,所有骰子朝上一面的点数之和为s,输入n,打印出s的所有可能的值出现的概率。
思路:n个骰子和最小为你,最大为6n,根据排列组合,n个骰子的所有点数的排列为6^n,我们需要先统计出每一种点数和的出现次数,然后除以6^n即为概率。动态规划分析如下:
当有n个骰子,点数和为s,则每一种点数和出现的次数记为f(n,s)。现在假设我有n-1个骰子,再增加一个骰子,它的点数只能是1到6,则n个骰子得到点数和为s的情况有6种,所以f(n,s)=f(n-1,s-1)+f(n-1,s-2)+…+f(n-1,s-6),当有一个骰子时,f(1,1)=f(1,2)=f(1,3)=f(1,4)=f(1,5)=f(1,6)=1。
具体到程序,用两个数组,在第一次循环中,第一个数组中的第s个数字表示和为s出现的次数。在下一次循环中,加上一个新骰子,此时和为s出现的次数等于上一次循环中和为s-1,s-2,s-3直到s-6出现次数的总和,所以把另一个数组的第s个数字设为前一个数组对应的第s-1,s-2,s-3直到s-6之和,下一轮循环交换数组重复这一过程。
Java实现如下:

public class Probability {
    static void printProbability(int number){
        if (number<1)
            return;
        int g_maxValue = 6;
        int[][] pProbabilitys = new int[2][g_maxValue * number + 1];
        int flag = 0; // 控制在2个数组间切换
        // 一个骰子时
        for (int i = 1; i <= g_maxValue; i++)
            pProbabilitys[flag][i] = 1;
        // 开始加骰子
        for (int k = 2; k <= number; k++) {
            // 不可能出现的次数标记为0
            for (int i = 0; i < k; i++)
                pProbabilitys[1-flag][i] = 0;
            // 可能出现的次数
            for (int i = k; i <= g_maxValue*number; i++) {
                pProbabilitys[1-flag][i] = 0;
                for (int j = 1; j <= i && j <= g_maxValue; j++) 
                    pProbabilitys[1-flag][i] += pProbabilitys[flag][i-j];                
            }
            flag = 1-flag;
        }
        double total = Math.pow(g_maxValue, number);
        for (int i = 1; i <= g_maxValue*number; i++) {
            double ratio = pProbabilitys[flag][i] / total;
            System.out.println(i + ": " + ratio);
        }
    }

    public static void main(String[] args) {
        printProbability(1);
    }
}

面试题44:扑克牌的顺子

从一副牌中随机抽取5张判断是不是顺子,A为1,大小王可为任意值。
思路:把5张牌看成大小为5的数组,大小王视为0,首先把数组排序,再统计数组中0的个数,还要统计有序数组中相邻数字之间的空缺数,去和0的个数相比,0比空缺数多的话就是顺子。
Java实现如下:

import java.util.Arrays;
public class IsContinuous {
    static boolean isContinuous(int[] arr) {
        if (arr == null || arr.length < 1)
            return false;
        int length = arr.length;
        Arrays.sort(arr);
        int numbersOfZero = 0;
        int numberOfGap = 0;
        for (int i = 0; i < length && arr[i] == 0; i++)
            ++numbersOfZero;
        int notZeroIndex = numbersOfZero;
        while (notZeroIndex < length-1) {
            // 有重复的数肯定不是顺子
            if (arr[notZeroIndex] == arr[notZeroIndex+1])
                return false;
            numberOfGap += arr[notZeroIndex+1] - arr[notZeroIndex] - 1;
            notZeroIndex++;
        }
        return numberOfGap > numbersOfZero ? false : true;
    }
    public static void main(String[] args) {
        System.out.println(isContinuous(new int[]{2,4,5,0,0}));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值