问题描述
在一场经典的德州扑克游戏中,有一种牌型叫做“葫芦”。“葫芦”由五张牌组成,其中包括三张相同牌面值的牌 aa 和另外两张相同牌面值的牌 bb。如果两个人同时拥有“葫芦”,我们会优先比较牌 aa 的大小,若牌 aa 相同则再比较牌 bb 的大小。
在这个问题中,我们对“葫芦”增加了一个限制:组成“葫芦”的五张牌牌面值之和不能超过给定的最大值 maxmax。牌面值的大小规则为:A > K > Q > J > 10 > 9 > ... > 2,其中 A 的牌面值为1,K 为13,依此类推。
给定一组牌,你需要找到符合规则的最大的“葫芦”组合,并输出其中三张相同的牌面和两张相同的牌面。如果找不到符合条件的“葫芦”,则输出 “0, 0”。
解决思路
-
统计每个数字的出现次数:
- 使用哈希表统计每个数字在数组中的出现次数。
-
筛选符合条件的数字:
- 找出出现次数大于等于3的数字。
- 找出出现次数大于等于2的数字。
-
排序:
- 对筛选出的数字进行排序,方便后续处理。
-
组合选择:
- 遍历筛选出的数字,找到符合条件的组合。
易错点
有些葫芦,三带二的二,可能出现不只2次。如果要开两个数组对出现了3次以上和2次的数字进行统计,可能会忽略开头说的这一种情况。 此外,对于1比13地位高的问题,直接用条件语句判断即可。
重点解释
- 统计每个数字的出现次数:
std::unordered_map<int, int> countOccurrences(const std::vector<int>& array) {
std::unordered_map<int, int> countMap;
for (int num : array) {
if (countMap.find(num) != countMap.end()) {
countMap[num]++;
} else {
countMap[num] = 1;
}
}
return countMap;
}
- 筛选符合条件的数字:
- 找出出现次数大于等于3的数字:
std::vector<int> findKeysWithCountGreaterThanThree(const std::unordered_map<int, int>& countMap) {
std::vector<int> result;
for (const auto& pair : countMap) {
if (pair.second >= 3) {
result.push_back(pair.first);
}
}
return result;
}
- 找出出现次数大于等于2的数字:
std::vector<int> findKeysWithCountTwo(const std::unordered_map<int, int>& countMap) {
std::vector<int> result;
for (const auto& pair : countMap) {
if (pair.second >= 2) {
result.push_back(pair.first);
}
}
return result;
}
- 排序:
vector<int> vec3 = findKeysWithCountGreaterThanThree(result);
vector<int> vec2 = findKeysWithCountTwo(result);
std::sort(vec3.begin(), vec3.end(), greater<int>());
std::sort(vec2.begin(), vec2.end(), greater<int>());
- 组合选择
if (vec3.empty()) { return {0, 0}; }
if (!vec2.empty()) {
for (int a : vec3) {
for (int b : vec2) {
if (vec3.back() == 1 && (3 * 1 + 2 * b <= max)) {
if (b != 1) return {1, b};
}
if (vec3.back() == 1 && (3 * 1 + 2 * a <= max)) {
if (a != 1) return {1, a};
}
if (vec2.back() == 1 && (3 * a + 2 * 1 <= max) && a != 1) { return {a, 1}; }
if (vec2.back() != 1 && 3 * a + 2 * b <= max && a != b) {
return {a, b};
}
}
}
}
return {0, 0};