青训营X豆包MarsCode技术训练营第一课 | 豆包MarsCode AI刷题

37 阅读3分钟

题目:寻找最大葫芦

这个问题的核心是要在给定的牌面数组中,寻找一个符合“葫芦”规则的最大牌型,同时满足牌面值的总和不能超过给定的 max。在“葫芦”中,我们有三张相同的牌 a 和两张相同的牌 b,其中需要优先比较三张相同牌的大小,若三张相同牌大小相同,则再比较两张相同牌的大小。

解决思路:

  1. 牌面值映射
  • 我们首先需要处理牌面值的映射关系,即 A > K > Q > J > 10 > 9 > ... > 2。我们可以通过一个字典来存储这些值的映射关系。
  1. 频次统计
  • 使用字典来统计每个牌面出现的次数。一个牌面值出现的次数越多,我们就越有可能利用它来组成“葫芦”。
  1. 构建候选葫芦
  • 遍历所有可能的牌面组合,检查是否能构成“葫芦”(即出现频次至少为 3 的牌面和频次至少为 2 的牌面),并计算其总和,确保总和不超过 max。
  1. 排序与输出
  • 对于符合条件的“葫芦”,优先比较三张相同牌的大小,如果三张相同牌相同,则再比较两张相同牌的大小,最终输出符合条件的最大“葫芦”。

步骤:

  1. 对输入的牌面数组进行频次统计。
  2. 生成所有可能的“葫芦”组合(即三张相同和两张相同的牌面),并计算总和。
  3. 遍历所有合法组合,选择最大的一个。

代码实现:

from collections import Counter 
# 构建牌面值的映射 
card_value = { 'A': 1, 'K': 13, 'Q': 12, 'J': 11, '10': 10, '9': 9, '8': 8, '7': 7, '6': 6, '5': 5, '4': 4, '3': 3, '2': 2 } 
# 将牌面数字转化为对应的数值 
def get_card_value(card): 
    if card == 'A': 
        return 1 
    if card == 'K': 
        return 13 
    if card == 'Q': 
        return 12 
    if card == 'J': 
        return 11 
    return card_value[card] 

def solution(n, max_sum, array): 
    # 统计牌面频次 
    counter = Counter(array) 
    # 存储所有符合条件的葫芦 
    full_houses = [] 
    # 遍历所有出现至少 3 次的牌面组合 
    for a in counter: 
        if counter[a] >= 3: 
            # 找到一个三张相同牌面 a 
            for b in counter: 
                if a != b and counter[b] >= 2: 
                    # 找到一个两张相同牌面 b 
                    total_sum = a * 3 + b * 2 
                    if total_sum <= max_sum: 
                        full_houses.append((a, b)) 
    # 排序:首先按 a 的大小降序,如果 a 相同则按 b 的大小降序 
    full_houses.sort(key=lambda x: (x[0], x[1]), reverse=True) 
    
    # 返回符合条件的最大的葫芦 
    if full_houses: 
        return full_houses[0] 
    else: 
        return [0, 0] 
# 测试样例 
n = 9 
max_sum = 34 
array = [6, 6, 6, 8, 8, 8, 5, 5, 1] 
result = solution(n, max_sum, array) 
print(result)

解释:

  1. get_card_value(card)
  • 这个函数将牌面值(比如 'A', 'K', 'Q', 'J', '10', '9', ..., '2')映射为对应的数值。
  1. find_best_full_house(n, max_sum, array)
  • 这个函数是核心部分,首先统计所有牌面出现的次数,然后生成符合条件的“葫芦”,并通过排序来选择最大的组合。
  1. 排序
  • 首先根据三张相同的牌(a)的大小排序,如果相同,再根据两张相同的牌(b)的大小排序。
  1. 输出
  • 如果找到符合条件的“葫芦”,输出其 a 和 b,否则返回 [0, 0]。

结果:

对于样例输入:

n = 9 max_sum = 34 array = [6, 6, 6, 8, 8, 8, 5, 5, 1]

输出结果为:

[8, 5]

这表示我们找到的最大“葫芦”是由三张 8 和两张 5 组成的,且其总和不超过 34。

时间复杂度:

  • 统计频次的时间复杂度为 O(n)。
  • 枚举所有可能的三张和两张牌的组合的时间复杂度是 O(k^2),其中 k 是不同牌面的数量(在最坏的情况下是 13)。
  • 总的时间复杂度为 O(n + k^2),其中 n 是牌的数量,k 是牌面的种类数。

优化:

  • 在处理频次统计时,如果一个牌面值的数量大于 2,可以跳过不符合要求的组合。