寻找最大葫芦
题目分析
题目描述
在一组扑克牌中,寻找符合“葫芦”规则的牌型组合。“葫芦”是由三张相同牌面值和两张相同牌面值的牌组成,且总和值不能超过给定的最大值 max。如果有多个符合条件的组合,优先选择三张牌面值更大的组合;若三张牌面值相同,再比较两张牌面值。
解题思路
核心思路分解:
-
统计牌的频率
使用哈希表(std::unordered_map)统计每张牌的数量,以便快速判断哪些牌可以组成三张或两张的组合。 -
生成组合
遍历所有可能的三张牌和两张牌的组合,筛选出符合“葫芦”规则的组合,并记录其三张和两张的牌面值。 -
筛选最优解
根据牌面值的优先级进行排序:- 先比较三张牌的值。
- 若三张牌相同,再比较两张牌的值。
同时确保五张牌的总和不超过给定的最大值max。
-
特殊情况处理
- 如果找不到符合条件的组合,返回
{0, 0}。
- 如果找不到符合条件的组合,返回
C++ 实现
代码逻辑详解:
#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
// 定义解决方案函数
std::vector<int> solution(int n, int max, const std::vector<int> &array) {
// Step 1: 统计每张牌的出现次数
std::unordered_map<int, int> count;
for (int card : array) {
count[card]++;
}
// Step 2: 枚举所有可能的三张和两张组合
std::vector<std::pair<int, int>> possible_combos;
for (auto &[card1, cnt1] : count) {
if (cnt1 >= 3) { // 三张牌
for (auto &[card2, cnt2] : count) {
if (card1 != card2 && cnt2 >= 2) { // 两张牌
possible_combos.push_back({card1, card2});
}
}
}
}
// Step 3: 筛选符合条件的组合
std::pair<int, int> best_combo = {0, 0};
for (auto &[a, b] : possible_combos) {
// 检查总和值是否满足条件
if (3 * a + 2 * b <= max) {
int a_value = (a == 1) ? 14 : a; // 特殊处理A为最大牌
int b_value = (b == 1) ? 14 : b; // 特殊处理A为最大牌
// 按优先级更新最优解
if (a_value > best_combo.first ||
(a_value == best_combo.first && b_value > best_combo.second)) {
best_combo = {a_value, b_value};
}
}
}
// Step 4: 若找不到合适组合,返回 {0, 0}
if (best_combo.first == 0 && best_combo.second == 0) {
return {0, 0};
}
// 返回原始牌面值
return {best_combo.first == 14 ? 1 : best_combo.first,
best_combo.second == 14 ? 1 : best_combo.second};
}
int main() {
// 测试样例 1
std::vector<int> result1 = solution(9, 34, {6, 6, 6, 8, 8, 8, 5, 5, 1});
std::cout << (result1 == std::vector<int>{8, 5}) << std::endl; // 输出: 1 (true)
// 测试样例 2
std::vector<int> result2 = solution(9, 37, {9, 9, 9, 9, 6, 6, 6, 6, 13});
std::cout << (result2 == std::vector<int>{6, 9}) << std::endl; // 输出: 1 (true)
// 测试样例 3
std::vector<int> result3 = solution(9, 40, {1, 11, 13, 12, 7, 8, 11, 5, 6});
std::cout << (result3 == std::vector<int>{0, 0}) << std::endl; // 输出: 1 (true)
return 0;
}
知识点总结
-
哈希表的使用
- 通过
std::unordered_map快速统计元素的频率,效率远高于手动遍历数组。
- 通过
-
优先级排序与筛选
- 在生成可能的组合后,需要根据优先级条件更新最优解,这是常见的动态比较逻辑。
-
边界值处理
- 特殊值(如 A)的处理非常重要,通过逻辑调整避免出错。
学习建议
-
掌握 STL 容器
熟悉常用容器(如unordered_map和vector),特别是在统计与筛选场景下的应用。 -
分步调试
将复杂问题分解为多个步骤(如频率统计、组合生成、筛选最优),逐步调试,便于发现问题。 -
总结规律
多练习类似题目,总结问题的通用解法(如优先级排序、条件筛选),提升解题能力。
学习计划
-
每日刷题计划
- 每天完成 1-2 道数组、哈希表相关的题目,巩固基本功。
-
错题回顾
- 针对边界处理或逻辑漏洞的题目,整理错题笔记并进行复盘。
-
应用场景扩展
- 将类似问题的逻辑应用到其他问题场景,练习算法的迁移能力。
通过本题的练习,不仅掌握了 C++ STL 的使用,还学习了如何设计优先级筛选和组合逻辑。这种分步解决问题的方法可以应用于更多复杂的算法题中。