哈希表的应用实例
1.例题
问题描述:
在一场经典的德州扑克游戏中,有一种牌型叫做“葫芦”。“葫芦”由五张牌组成,其中包括三张相同牌面值的牌 aa 和另外两张相同牌面值的牌 bb。如果两个人同时拥有“葫芦”,我们会优先比较牌 aa 的大小,若牌 aa 相同则再比较牌 bb 的大小。
在这个问题中,我们对“葫芦”增加了一个限制:组成“葫芦”的五张牌牌面值之和不能超过给定的最大值 maxmax。牌面值的大小规则为:A > K > Q > J > 10 > 9 > ... > 2,其中 A 的牌面值为1,K 为13,依此类推。
给定一组牌,你需要找到符合规则的最大的“葫芦”组合,并输出其中三张相同的牌面和两张相同的牌面。如果找不到符合条件的“葫芦”,则输出 “0, 0”。
个人解题思路:
由题目可以知道,“葫芦”组合是指 aaabb组合,并且,3a+2b<=max,那么对于给定的数组,只需要判断这个数组中是否存在两个数a和b,其中a出现了三次,b出现了两次,并且3a+2b<=max 那么要实现的就是统计数组中每个数出现的次数,使用哈希表,即HashMap,就可以实现这个问题;
题目难以理解的点
牌面值的大小规则为:A > K > Q > J > 10 > 9 > ... > 2,其中 A 的牌面值为1,K 为13,依此类推。
解释:A的面值是1,表示在给定的牌数组中,1代表A,但是在与max值进行比较时,却要使用14,因为A > K > Q > J > 10 > 9 > ... > 2,其中 A 的牌面值为1,K 为13,所以1即A就是14,为了防止搞混,我们可以再创建一个哈希表valueMap,用来映射面值和真实值(权重)
2.Java中HashMap的语法
1.简单介绍
HashMap 是一个散列表,它存储的内容是键值对(key-value)映射。
HashMap 实现了 Map 接口,根据键的 HashCode 值存储数据,具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
HashMap 是无序的,即不会记录插入的顺序。
2.使用
HashMap 类位于 java.util 包中,使用前需要引入它,语法格式如下:
import java.util.HashMap; // 引入 HashMap 类
以下实例我们创建一个 HashMap 对象 Sites, 整型(Integer)的 key 和字符串(String)类型的 value:
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
添加元素:
HashMap 类提供了很多有用的方法,添加键值对(key-value)可以使用 put() 方法:
// 创建 HashMap 对象 Sites
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
// 添加键值对
Sites.put(1, "Google");
访问元素:
我们可以使用 get(key) 方法来获取 key 对应的 value:
System.out.println(Sites.get(1));
删除元素:
我们可以使用 remove(key) 方法来删除 key 对应的键值对(key-value):
Sites.remove(1);
删除所有键值对(key-value)可以使用 clear 方法:
Sites.clear();
计算大小
如果要计算 HashMap 中的元素数量可以使用 size() 方法。
迭代 HashMap
可以使用 for-each 来迭代 HashMap 中的元素。
如果你只想获取 key,可以使用 keySet() 方法,然后可以通过 get(key) 获取对应的 value,如果你只想获取 value,可以使用 values() 方法。
其他方法:
3.本题代码实现
import java.util.HashMap;
import java.util.Map;
public class Main {
public static int[] solution(int n, int max, int[] array) {
// 初始化哈希表
Map<Integer, Integer> countMap = new HashMap<>();
// 统计每个牌面值的出现次数
for (int num : array) {
countMap.put(num, countMap.getOrDefault(num, 0) + 1);
}
// 牌面值映射表
Map<Integer, Integer> valueMap = new HashMap<>();
valueMap.put(1, 14); // A -> 14
valueMap.put(2, 2);
valueMap.put(3, 3);
valueMap.put(4, 4);
valueMap.put(5, 5);
valueMap.put(6, 6);
valueMap.put(7, 7);
valueMap.put(8, 8);
valueMap.put(9, 9);
valueMap.put(10, 10);
valueMap.put(11, 11); // J -> 11
valueMap.put(12, 12); // Q -> 12
valueMap.put(13, 13); // K -> 13
int maxThree = 0;
int maxTwo = 0;
// 查找符合条件的“葫芦”组合
for (int a : countMap.keySet()) {
if (countMap.get(a) >= 3) {
for (int b : countMap.keySet()) {
if (a != b && countMap.get(b) >= 2) {
int sum = 3 * a + 2 * b;
if (sum <= max) {
int mappedA = valueMap.get(a);
int mappedB = valueMap.get(b);
if (mappedA > valueMap.getOrDefault(maxThree, 0) ||
(mappedA == valueMap.getOrDefault(maxThree, 0) && mappedB > valueMap.getOrDefault(maxTwo, 0))) {
maxThree = a;
maxTwo = b;
}
}
}
}
}
}
// 返回结果
return new int[]{maxThree, maxTwo};
}
public static void main(String[] args) {
// 添加测试用例
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}));
System.out.println(java.util.Arrays.equals(solution(31, 42, new int[]{3,3,11,12,12,2,13,5,13,1,13,8,8,1,8,13,12,9,2,11,3,5,8,11,1,11,1,5,4,2,5}), new int[]{1, 13}));
}
}