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;
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章