青训营X豆包MarsCode 技术训练营第五课 | 豆包MarsCode AI 刷题

62 阅读4分钟

问题描述

在一场经典的德州扑克游戏中,有一种牌型叫做“葫芦”。“葫芦”由五张牌组成,其中包括三张相同牌面值的牌 a 和另外两张相同牌面值的牌 b。如果两个人同时拥有“葫芦”,我们会优先比较牌 aa 的大小,若牌 a 相同则再比较牌 bb 的大小。

在这个问题中,我们对“葫芦”增加了一个限制:组成“葫芦”的五张牌牌面值之和不能超过给定的最大值 max。牌面值的大小规则为:A > K > Q > J > 10 > 9 > ... > 2,其中 A 的牌面值为1,K 为13,依此类推。

给定一组牌,你需要找到符合规则的最大的“葫芦”组合,并输出其中三张相同的牌面和两张相同的牌面。如果找不到符合条件的“葫芦”,则输出 “0, 0”。

问题解析

这个问题是关于组合优化的问题,需要在德州扑克的规则下找到最大的“葫芦”组合,同时满足牌面值之和不超过给定的最大值 max。这个问题可以通过贪心算法和排序的思想来解决。

思路与图解

  1. 统计牌面值:首先统计每种牌面值的数量,因为“葫芦”需要三张相同的牌和两张相同的牌,所以需要统计每种牌面值出现的次数。
  2. 寻找最大的a:在满足牌面值之和不超过 max 的条件下,寻找可以作为“葫芦”中三张相同牌面值的最大值 a
  3. 寻找最大的b:在确定了 a 之后,寻找可以作为“葫芦”中两张相同牌面值的最大值 b
  4. 验证和是否满足条件:确保 3a + 2b 的和不超过 max

图解如下:

统计牌面值 -> 寻找最大的a -> 寻找最大的b -> 验证和是否满足条件 -> 输出结果

代码注释解析

import java.util.Arrays;

public class Main {
    public static int[] solution(int n, int max, int[] array) {
        // 标记数组,用于统计每种牌面值的数量
        int[] a = new int[14];
        int i = 0;
        int j = 0; // a
        int k = 0; // b
        int l = 0;

        // 统计每种牌面值的数量
        for (i = 0; i < n; i++) {
            a[array[i]]++; // 数量增加
        }

        // 寻找最大的a
        if (a[1] >= 3) { // A可以作为a
            j = 1;
            // 寻找最大的b
            for (i = 13; i > 1; i--) {
                if (a[i] >= 2 && 3 + i * 2 <= max) { // 找到符合条件的b
                    k = i;
                    break;
                }
            }
        } else { // A不能作为a
            for (i = 13; i > 1; i--) {
                if (a[i] >= 3 && a[1] >= 2 && i * 3 + 2 <= max) { // i可以作为a,A作为b
                    j = i;
                    k = 1;
                    break;
                }
                for (l = 13; l > 0; l--) {
                    if (a[i] >= 3 && a[l] >= 2 && i != l && i * 3 + l * 2 <= max) { // 找到符合条件的b
                        j = i;
                        k = l;
                        break;
                    }
                }
                if (j != 0 || k != 0) {
                    break;
                }
            }
        }

        // 如果没有找到符合条件的a和b,返回{0, 0}
        if (j == 0 || k == 0) {
            return new int[]{0, 0};
        } else {
            return new int[]{j, k};
        }
    }

    public static void main(String[] args) {
        // 测试用例
        int n = 9;
        int max = 34;
        int[] array = {6, 6, 6, 8, 8, 8, 1, 5, 5};
        System.out.println(Arrays.toString(solution(n, max, array)));
    }
}

新知识点总结

  1. 贪心算法:在满足条件的前提下,优先选择最大的牌面值作为“葫芦”的一部分。
  2. 数组和循环:使用数组来统计每种牌面值的数量,并使用循环来寻找最大的牌面值。

学习建议

对于入门同学来说,理解贪心算法和循环结构是非常重要的。可以通过解决类似的组合优化问题来加深理解。同时,要注意代码的逻辑性和效率,这在处理大规模数据问题时尤为重要。 AI 刷题功能可以帮助你快速理解问题和解决方案,但要深入学习,还需要结合其他资源。例如,可以通过在线课程学习算法基础,通过LeetCode等平台练习算法题,以及阅读相关书籍来加深理解。同时,可以加入技术社区,与其他学习者交流心得,共同进步。

实用学习建议

  1. 社区交流:加入技术社区,与其他学习者交流,解决学习中遇到的问题。
  2. 定期复习:定期复习已学知识,通过解决新问题来巩固旧知识。