一、算法問題描述
隨機取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;
}
}