最大葫芦 | 豆包MarsCode AI刷题

166 阅读3分钟

寻找最大葫芦

题目分析

题目描述
在一组扑克牌中,寻找符合“葫芦”规则的牌型组合。“葫芦”是由三张相同牌面值和两张相同牌面值的牌组成,且总和值不能超过给定的最大值 max。如果有多个符合条件的组合,优先选择三张牌面值更大的组合;若三张牌面值相同,再比较两张牌面值。


解题思路

核心思路分解

  1. 统计牌的频率
    使用哈希表(std::unordered_map)统计每张牌的数量,以便快速判断哪些牌可以组成三张或两张的组合。

  2. 生成组合
    遍历所有可能的三张牌和两张牌的组合,筛选出符合“葫芦”规则的组合,并记录其三张和两张的牌面值。

  3. 筛选最优解
    根据牌面值的优先级进行排序:

    • 先比较三张牌的值。
    • 若三张牌相同,再比较两张牌的值。
      同时确保五张牌的总和不超过给定的最大值 max
  4. 特殊情况处理

    • 如果找不到符合条件的组合,返回 {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;
}

知识点总结

  1. 哈希表的使用

    • 通过 std::unordered_map 快速统计元素的频率,效率远高于手动遍历数组。
  2. 优先级排序与筛选

    • 在生成可能的组合后,需要根据优先级条件更新最优解,这是常见的动态比较逻辑。
  3. 边界值处理

    • 特殊值(如 A)的处理非常重要,通过逻辑调整避免出错。

学习建议

  • 掌握 STL 容器
    熟悉常用容器(如 unordered_mapvector),特别是在统计与筛选场景下的应用。

  • 分步调试
    将复杂问题分解为多个步骤(如频率统计、组合生成、筛选最优),逐步调试,便于发现问题。

  • 总结规律
    多练习类似题目,总结问题的通用解法(如优先级排序、条件筛选),提升解题能力。


学习计划

  1. 每日刷题计划

    • 每天完成 1-2 道数组、哈希表相关的题目,巩固基本功。
  2. 错题回顾

    • 针对边界处理或逻辑漏洞的题目,整理错题笔记并进行复盘。
  3. 应用场景扩展

    • 将类似问题的逻辑应用到其他问题场景,练习算法的迁移能力。

通过本题的练习,不仅掌握了 C++ STL 的使用,还学习了如何设计优先级筛选和组合逻辑。这种分步解决问题的方法可以应用于更多复杂的算法题中。