baby-gin 算法

一、算法问题描述
随机取6张牌,牌上的数字为 0 ~ 9,可以重复,组成 baby-gin算法的条件:1个run + 1 个trip或者2个run或者2个trip 类型
一种组合为 run(1,2,3),三张牌为顺子,另一种为trip(1,1,1),三张牌相同。
二、算法分析
1.暴力查询法(慢)
(1).先从6张牌中任意选取3张自由组合,也就是C6(3),共有20种不同的组合。

public class BabyGin {

    public static void main(String[] args){

        int[] baby = {1,3,5,6,2,2};
        BabyGin.select3(baby);
    }

    // 从 6 张牌中任意选取3张
    public static int[] select3(int[] baby6){
        int[] baby3 = new int[3];   // 创建一个存放组合的数组
        int count = 0;
        for(int i = 0;i < baby6.length - 2;i++){
            for(int j = i+1;j < baby6.length - 1;j++){
                for(int k = j+1;k < baby6.length;k++){
                    baby3[0] = baby6[i];
                    baby3[1] = baby6[j];
                    baby3[2] = baby6[k];
                    // 20种排好序
                    System.out.println("第" + (count+1) + "种,[" + baby3[0] + "," + baby3[1] + "," + baby3[2] + "]");
                    count++;
                }
            }
        }
        return baby3;
    }

}

(2).将组合起来的20种组合分别排序,建议从小到大排序。

// 冒泡排序,将选取的3张牌从小到大排序
    public static int[] bubble(int[] select3){

        for(int i = 0;i < select3.length - 1;i++){
            for(int j = i + 1;j < select3.length;j++){
                if(select3[i] > select3[j]){
                    int temp = select3[j];
                    select3[j] = select3[i];
                    select3[i] = temp;  
                }
            }
        }

        return select3;
    }

(3).判断是否符合baby-gin算法需求,有一种run/trip组合,就计一次数,计满2次就符合baby-gin算法。

// 判断是否为 run / trip,前提条件是传入的数组已经从小到大排好序
    public static boolean countRunOrTrip(int[] bubble) {
        boolean flag = false;
        if (bubble[0] == (bubble[1] - 1)) {
            if (bubble[1] == (bubble[2] - 1)) {
                flag = true;
            }
        } else if (bubble[0] == bubble[1]) {
            if (bubble[1] == bubble[2]) {
                flag = true;
            }
        }
        return flag;
    }

(4) 最终代码

package com.daxiong.encode;

public class BabyGin {

    public static void main(String[] args) {

        int[] baby = { 1, 1, 2, 2, 3, 3 };
        BabyGin.select3(baby);

    }

    // 从 6 张牌中任意选取3张
    public static int[] select3(int[] baby6) {
        int[] baby3 = new int[3]; // 创建一个存放组合的数组
        int count = 0;
        int yesCount = 0;
        for (int i = 0; i < baby6.length - 2; i++) {
            for (int j = i + 1; j < baby6.length - 1; j++) {
                for (int k = j + 1; k < baby6.length; k++) {
                    baby3[0] = baby6[i];
                    baby3[1] = baby6[j];
                    baby3[2] = baby6[k];
                    // 20种排好序
                    System.out.println("第" + (count + 1) + "种,[" + baby3[0] + "," + baby3[1] + "," + baby3[2] + "]组合");
                    int[] bubble = BabyGin.bubble(baby3);
                    System.out.print("排序后,[" + bubble[0] + "," + bubble[1] + "," + bubble[2] + "]");
                    boolean flag = BabyGin.countRunOrTrip(bubble);
                    System.out.print(" ," + flag);
                    System.out.println();
                    if (flag) {
                        yesCount++;
                    }
                    count++;
                }
            }
        }

        if (yesCount >= 2) {
            System.out.println("YES 该数组为 baby-gin");
        } else {
            System.out.println("NO 该数组不是 baby-gin");
        }
        return baby3;
    }

    // 冒泡排序,将选取的3张牌从小到大排序
    public static int[] bubble(int[] select3) {
        for (int i = 0; i < select3.length - 1; i++) {
            for (int j = i + 1; j < select3.length; j++) {
                if (select3[i] > select3[j]) {
                    int temp = select3[j];
                    select3[j] = select3[i];
                    select3[i] = temp;
                }
            }
        }
        return select3;
    }

    // 判断是否为 run / trip,前提条件是传入的数组已经从小到大排好序
    public static boolean countRunOrTrip(int[] bubble) {
        boolean flag = false;
        if (bubble[0] == (bubble[1] - 1)) {
            if (bubble[1] == (bubble[2] - 1)) {
                flag = true;
            }
        } else if (bubble[0] == bubble[1]) {
            if (bubble[1] == bubble[2]) {
                flag = true;
            }
        }
        return flag;
    }
}

2.计数法(高效,快速)
(1).先统计给定6张牌出现0~9的次数,并记录

// 统计0~9出现的频率
    public  static int[] countHZ(int[] baby){
        int[] baby09 = {0,0,0,0,0,0,0,0,0,0};   // 0 ~ 9 出现的次数
        for(int i = 0;i < baby.length;i++){
            for(int j = 0; j < 9;j++){
                if(baby[i] == j){
                    baby09[j] = baby09[j] + 1;
                }
            }
        }
        return baby09;
    }

(2)判断是否为 baby-gin 算法
需要注意:112233,这种情况,当判断0~9中123的个人分别都大于0时,同时减去1,还回剩下123,此时需要再次调用该方法,才会执行,所以这里采用递归调用的方式,如果调用完第一次后0~9中频率还大于0,此时再次调用

// 判断是否为 baby-gin 算法
    public static int countBabyGin(int[] baby09) {

        int count = 0;
        int flag = 0;
        for (int i = 0; i < baby09.length - 2; i++) {
            if (baby09[i] >= 3) { // 说明至少有一个 trip
                baby09[i] = baby09[i] - 3;
                count++;
            } else if (baby09[i] > 0 && baby09[i + 1] > 0 && baby09[i + 2] > 0) {
                baby09[i] = baby09[i] - 1;
                baby09[i + 1] = baby09[i + 1] - 1;
                baby09[i + 2] = baby09[i + 2] - 1;
                count++;
            }
            if (baby09[i] != 0) {
                flag++;
            }
        }
        System.out.println("flag =" + flag);
        for (int i = 0; i < 9; i++) {
            System.out.println("baby09 =" + baby09[i]);
        }
        if(flag > 0){   // 递归调用,需要注意递归调用结束的条件
            count = count + BabyGin2.countBabyGin(baby09);
        }
        return count;
    }

(3)整体代码

package com.daxiong.encode;

public class BabyGin2 {

    public static void main(String[] args) {
        int[] baby = { 1, 1, 2, 2, 3, 3 };
        System.out.println(BabyGin2.countBabyGin(BabyGin2.countHZ(baby)));
        int[] baby09 = BabyGin2.countHZ(baby);
        int countFlag = BabyGin2.countBabyGin(baby09);

        if(countFlag >= 2){
            System.out.println("YES 该数组为 baby-gin");
        } else{
            System.out.println("NO 该数组不是 baby-gin");
        } 
    }

    // 统计0~9出现的频率
    public static int[] countHZ(int[] baby) {
        int[] baby09 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // 0 ~ 9 出现的次数
        for (int i = 0; i < baby.length; i++) {
            for (int j = 0; j < 9; j++) {
                if (baby[i] == j) {
                    baby09[j] = baby09[j] + 1;
                }
            }
        }
        return baby09;
    }

    // 判断是否为 baby-gin 算法
    public static int countBabyGin(int[] baby09) {

        int count = 0;
        int flag = 0;
        for (int i = 0; i < baby09.length - 2; i++) {
            if (baby09[i] >= 3) { // 说明至少有一个 trip
                baby09[i] = baby09[i] - 3;
                count++;
            } else if (baby09[i] > 0 && baby09[i + 1] > 0 && baby09[i + 2] > 0) {
                baby09[i] = baby09[i] - 1;
                baby09[i + 1] = baby09[i + 1] - 1;
                baby09[i + 2] = baby09[i + 2] - 1;
                count++;
            }
            if (baby09[i] != 0) {
                flag++;
            }
        }
        System.out.println("flag =" + flag);
        for (int i = 0; i < 9; i++) {
            System.out.println("baby09 =" + baby09[i]);
        }
        if(flag > 0){   // 递归调用,需要注意递归调用结束的条件
            count = count + BabyGin2.countBabyGin(baby09);
        }
        return count;
    }
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值