寻找最大葫芦(字节青训)

问题描述

在一场经典的德州扑克游戏中,有一种牌型叫做“葫芦”。“葫芦”由五张牌组成,其中包括三张相同牌面值的牌 aa 和另外两张相同牌面值的牌 bb。如果两个人同时拥有“葫芦”,我们会优先比较牌 aa 的大小,若牌 aa 相同则再比较牌 bb 的大小,牌面值的大小规则为:1 (A) > K > Q > J > 10 > 9 > ... > 2,其中 1 (A) 的牌面值为1,K 为13,依此类推。

在这个问题中,我们对“葫芦”增加了一个限制:组成“葫芦”的五张牌牌面值之和不能超过给定的最大值 maxmax。

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

测试样例

样例1:

输入:n = 9, max = 34, array = [6, 6, 6, 8, 8, 8, 5, 5, 1]
输出:[8, 5]
说明:array数组中可组成4个葫芦,分别为[6,6,6,8,8],[6,6,6,5,5],[8,8,8,6,6],[8,8,8,5,5]。其中[8,8,8,6,6]的牌面值为36,大于34不符合要求。剩下的3个葫芦的大小关系为[8,8,8,5,5]>[6,6,6,8,8]>[6,6,6,5,5],故返回[8,5]

样例2:

输入:n = 9, max = 37, array = [9, 9, 9, 9, 6, 6, 6, 6, 13]
输出:[6, 9]
说明:可组成2个葫芦,分别为[9,9,9,6,6]和[6,6,6,9,9],由于[9,9,9,6,6]的牌面值为39,大于37,故返回[6,9]

样例3:

输入:n = 9, max = 40, array = [1, 11, 13, 12, 7, 8, 11, 5, 6]
输出:[0, 0]
说明:无法组成任何葫芦,故返回[0,0]

样例4:

输入:n = 6, max = 50, array = [13, 13, 13, 1, 1, 1]
输出:[1, 13]
说明:可组成两个葫芦,分别为[A,A,A,K,K]和[K,K,K,A,A],两者牌面值都小于50,故都合法。因为三张相同牌面值的A > K,故[A,A,A,K,K]比[K,K,K,A,A]要大,返回[1,13]

 思路
  1. 统计牌面值的出现次数:遍历牌组,使用 HashMap 统计每种牌面值的出现次数。
  2. 生成所有可能的“葫芦”组合
    • 遍历 HashMap,对于每个牌面值 a,如果出现次数大于等于3,再遍历其他牌面值 b,如果 b 的出现次数大于等于2,则生成一个“葫芦”组合。
    • 计算该组合的牌面值之和,如果小于等于 max,则将其加入到 List 中。
  3. 选择最大的“葫芦”组合
    • 遍历 List,根据题目要求的优先级(先比较 a,再比较 b)选择最大的“葫芦”组合。
  4. 返回结果:如果没有符合条件的“葫芦”组合,返回 [0, 0]

 

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import java.util.*;

public class Main {
    public static int[] solution(int n, int max, int[] array) {
        // Edit your code here
        List<Integer> aList=new ArrayList<>();
        List<Integer> bList=new ArrayList<>();
         // 使用HashMap来统计每个牌面值出现的次数
        HashMap<Integer,Integer> hashMap=new HashMap<>();
        for (int i = 0; i < array.length; i++) {
        hashMap.put(array[i], hashMap.getOrDefault(array[i], 0) + 1);
        }
         // 构建候选列表aList存储至少出现3次的牌面值,bList存储至少出现2次的牌面值
 for (Map.Entry<Integer, Integer> entry : hashMap.entrySet()) {
            int key = entry.getKey();
            int value = entry.getValue();
            if (value >= 3) {
                aList.add(key); // 满足3张也可满足2张
                bList.add(key);
            } else if (value >= 2) {
                bList.add(key);
            }
        }
        // 构建合法组合并排序并确保这些组合的牌面值之和不超过max
        List<int[]> combinations = new ArrayList<>();
        for (int a : aList) {
            for (int b : bList) {
                if (a != b) { // 避免重复使用同一张牌
                    int sum = 3 * a + 2 * b;
                    if (sum <= max) {
                        combinations.add(new int[]{a, b});
                    }
                }
            }
        }
        // 排序组合:优先按a降序,再按b降序
        combinations.sort((o1, o2) -> {
            //处理特殊情况
            //如果第一个对象的第一个字符为A 那么不交换顺序 返回false
            if (o1[0] == 1 && o2[0] != 1) return -1;
            //如果第二个对象的第一个字符为A 那么交换顺序 返回1 即true
            if (o1[0] != 1 && o2[0] == 1) return 1;
            //正常情况 比较两个对象的第一个字符的大小 如果不相同直接返回降序
            if (o1[0] != o2[0]) {
                return o2[0] - o1[0]; // a降序
            }else{
                //如果两个对象的第一个字符相同 比较第二个字符 
                //特殊情况第二个字符为A 
                //如果第一个对象的第二个字符为A 那么两个对象不交换顺序 返回false
            if (o1[1] == 1 && o2[1] != 1) return -1;
                //如果第二个对象的第二个字符为A 那么两个对象交换顺序 返回true
            if (o1[1] != 1 && o2[1] == 1) return 1;

            return o2[1] - o1[1]; // b降序

            }
            
        });
        if (combinations.isEmpty()) {
            return new int[]{0, 0};
        }
        return combinations.get(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}));
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值