学习心得与方法-易5-寻找最大葫芦-Java实现 | 豆包MarsCode AI刷题

56 阅读3分钟

技术文章:实现德州扑克“葫芦”牌型的最大组合

问题背景

在德州扑克游戏中,“葫芦”是一种由五张牌组成的特殊牌型,其中包括三张相同牌面值的牌(记为a)和另外两张相同牌面值的牌(记为b)。若两位玩家的“葫芦”牌型相同,则通过比较a的大小来判断大小,若a相同,则通过b的大小来进一步比较。

在本题中,我们增加了一个约束条件,即组成“葫芦”的五张牌的牌面值之和不能超过给定的最大值max,并且牌面值的大小规则如下:

  • A = 1
  • K = 13
  • Q = 12
  • J = 11
  • 10 = 10
  • 9 = 9
  • ...
  • 2 = 2

我们的目标是从给定的牌面数组中,找到符合规则的最大“葫芦”组合,并输出其中三张相同的牌面和两张相同的牌面。如果无法找到符合条件的“葫芦”,则输出[0, 0]

解决方案

  1. 统计每张牌的数量: 我们首先需要统计数组中每个牌面值出现的次数。这是通过一个大小为14的计数数组cnt来完成的,其中cnt[i]表示牌面值为i的牌的数量。

  2. 遍历所有可能的三张相同牌面值和两张相同牌面值的组合: 对于每一个可能的三张相同牌面(记为a),我们遍历所有可能的两张相同牌面(记为b)。同时,我们需要满足以下两个条件:

    • 牌a的数量必须大于或等于3。
    • 牌b的数量必须大于或等于2,并且a和b不能相同。
  3. 计算“葫芦”的牌面值总和: 对于每一组a和b,我们计算它们的牌面值总和,并判断是否满足总和不超过给定的max。如果符合条件,我们更新当前找到的“葫芦”牌型。

  4. 比较两个“葫芦”牌型的大小: 如果存在多个符合条件的“葫芦”牌型,我们需要通过牌a的大小来优先比较,若牌a相同,再通过牌b的大小来比较。

  5. 返回最大组合: 最后,我们返回找到的最大“葫芦”组合,若没有符合条件的“葫芦”,返回[0, 0]

代码实现

public static int[] solution(int n, int max, int[] array) {
    int[] cnt = new int[14];  // 记录每种牌面出现的次数
    for (int num : array) {
        cnt[num] += 1;  // 统计每个数字的出现次数
    }

    int maxA = 0;  // 最大的三张相同牌面值
    int maxB = 0;  // 最大的两张相同牌面值
    int sumOfHand = 0;  // 当前最大的“葫芦”的总和

    // 牌面值排序: A > K > Q > J > 10 > 9 > 8 > ... > 2
    int[] cards = new int[] { 1, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 };
    int[] value = new int[] { 15, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2 };  // 对应的牌面值
    
    // 遍历所有可能的三张相同牌面和两张相同牌面
    for (int i = 0; i < cards.length; i++) {
        int a = cards[i];
        if (cnt[a] >= 3) {  // 如果有三张a
            for (int j = 0; j < cards.length; j++) {
                int b = cards[j];
                if (cnt[b] >= 2 && a != b) {  // 如果有两张b,且a不等于b
                    int sumOfPoint = a * 3 + b * 2;  // 计算牌面值的和
                    int sumOfNewHand = value[i] * 3 + value[j] * 2;  // 根据优先规则计算新的牌面值
                    
                    if (sumOfPoint <= max && sumOfNewHand > sumOfHand) {  // 满足总和不超过max且找到更大的“葫芦”
                        if (a > maxA || (a == maxA && b > maxB)) {  // 优先比较a,再比较b
                            maxA = a;
                            maxB = b;
                            sumOfHand = sumOfNewHand;
                        }
                    }
                }
            }
        }
    }

    // 如果没有找到符合条件的“葫芦”,返回[0, 0]
    return new int[] { maxA, maxB };
}

复杂度分析

  1. 时间复杂度:

    • 统计每张牌出现的次数的时间复杂度是O(n),其中n是输入数组的长度。
    • 遍历所有可能的牌面组合进行计算,总共要检查13种牌面值,所以这是常数级别的,可以视为O(1)。

    因此,总的时间复杂度是O(n)。

  2. 空间复杂度:

    • 需要一个大小为14的计数数组cnt,所以空间复杂度是O(1)。

作者: AWM