寻找最大葫芦 | 豆包MarsCode AI刷题

128 阅读5分钟

AI刷题——寻找最大葫芦

题目如下

德州扑克是一种经典的扑克游戏,里面有一种牌型叫“葫芦”。
“葫芦”由五张牌组成,其中包含三张一样的牌a和另外两张一样的牌b。
“葫芦”跟“葫芦”之间可以比较大小,先比较a的大小,如果a一样大再比较b的大小。
德州扑克不包含大小王,只包含常规的52张牌。在13种不同的牌面里面,大小规则是A > K > Q > J > 10 > 9 > ... > 2。也就是说,A最大,K次之,2最小。
这里给“葫芦”加一个限制规则,“葫芦”的牌面值之和不能超过max(可以等于),A,2,3,...,J,Q,K的牌面值分别是1到13。

问题

给出n张牌,从里面寻找符合规则的最大葫芦组合

输入格式

第一行输入两个整数,代表牌的数量n和牌面值之和的限制max
第二行输入n个整数,代表n张牌的牌面,其中数字1代表牌面A,数字2到10分别代表牌面2到10,11代表牌面J,12代表牌面Q,13代码牌面K。

输出格式

最大的葫芦组合里面,三张的牌面和两张的牌面,如果没有葫芦则输出“0,0”

输入样式

样例1

9 34
6 6 6 8 8 8 5 5 1

样例2

9 37
9 9 9 9 6 6 6 6 13

样例3

9 40
1 11 13 12 7 8 11 5 6

输出样式

样例1

8 5

样例2

6 9

样例3

0 0

数据范围

牌数n的范围:5 < n < 40,0 < max < 100
牌面的范围:1 ≤ v ≤ 13
跟现实中扑克一样,每种牌面最多4张


思路分析

本题是一道简单题,直接使用暴力枚举即可,需要注意的是,由于在德州扑克游戏中,A是一个特殊的牌面,其大小是最大的,而牌面值却是最小的,仅为1,所以在选择葫芦组合时,应当将A作为一个特殊的牌进行考虑。除这张特殊牌外,其他的牌正常考虑,对每一种可能性进行尝试即可。

代码解析

首先,我们定义一个可以放置13个元素的整型数组count,用于存储每一种牌的数量。因为给定输入为每一张牌的牌面值组成的整型数组,而A的牌面值为1,所以遍历输入的数组,将每一个元素值放进我们定义好的数组中,其元素索引恰好与其牌面值-1相对应。

在查找最大“葫芦”的过程中,我们将牌组中有至少3张A的情况单独拎出来考虑,若存在3张A,则直接将3张A选出来组合牌型,然后再从大到小遍历剩下的牌组,当找到任意的不少于2张的牌,进行判断,组成的牌组牌面值之和是否符合小于等于max的要求,如果符合,就将其拎出来用于组合牌组并返回;否则继续循环找到最大且符合条件的牌。

若给定牌组中不存在3张A,则从最大的K开始从大到小进行遍历,找到后首先判断是否存在两张A,若存在则判断其构成的组合是否满足牌面值小于等于max的限制条件,满足则直接返回找到的牌组,不满足则再次对给定牌组进行遍历,找到最大且满足限制条件的2张牌返回。

值得注意的是,每次抽出3张卡牌时,需要相应的在count数组中进行记录,即卡牌对应数量减去3,然后在每次循环条件判断结束后再加回去看,以保证每次循环不会破坏牌组数量的有效性。


代码解答

public class Main {
    public static int[] solution(int n, int max, int[] array) {
        // 统计每种牌面值的数量
        int[] count = new int[13];
        for (int card : array) {
            count[card - 1]++;
        }

        // 优先考虑A作为三张相同牌面值的牌
        if (count[0] >= 3) {
            count[0] -= 3;
            for (int j = 12; j >= 1; j--) { // 不考虑A作为两张相同牌面值的牌
                if (count[j] >= 2) {
                    // 找到了两张相同牌面值的牌
                    if (3 + (j + 1) * 2 <= max) {
                        return new int[]{1, j + 1};
                    }
                }
            }
            // 恢复计数器
            count[0] += 3;
        }

        // 从最大的牌面值开始寻找“葫芦”组合
        for (int i = 12; i >= 1; i--) { // 不考虑A作为三张相同牌面值的牌
            if (count[i] >= 3) {
                // 找到了三张相同牌面值的牌
                count[i] -= 3;
                if(count[0] >= 2) {
                    if ((i + 1) * 3 + 2 <= max) {
                        return new int[]{i + 1, 1};
                    }
                }
                for (int j = 12; j >= 0; j--) {
                    if (count[j] >= 2) {
                        // 找到了两张相同牌面值的牌
                        if ((i + 1) * 3 + (j + 1) * 2 <= max) {
                            return new int[]{i + 1, j + 1};
                        }
                    }
                }
                // 恢复计数器
                count[i] += 3;
            }
        }

        // 没有找到符合条件的“葫芦”组合
        return new int[]{0, 0};
    }

    public static void main(String[] args) {
        // Add your test cases here
        System.out.println(java.util.Arrays.equals(solution(9, 34, new int[]{6, 6, 6, 8, 8, 8, 5, 5, 1}), new int[]{8, 5}));
        System.out.println(java.util.Arrays.equals(solution(9, 37, new int[]{9, 9, 9, 9, 6, 6, 6, 6, 13}), new int[]{6, 9}));
        System.out.println(java.util.Arrays.equals(solution(9, 40, new int[]{1, 11, 13, 12, 7, 8, 11, 5, 6}), new int[]{0, 0}));
    }
}