题目:寻找最大葫芦
这个问题的核心是要在给定的牌面数组中,寻找一个符合“葫芦”规则的最大牌型,同时满足牌面值的总和不能超过给定的 max。在“葫芦”中,我们有三张相同的牌 a 和两张相同的牌 b,其中需要优先比较三张相同牌的大小,若三张相同牌大小相同,则再比较两张相同牌的大小。
解决思路:
- 牌面值映射
- 我们首先需要处理牌面值的映射关系,即 A > K > Q > J > 10 > 9 > ... > 2。我们可以通过一个字典来存储这些值的映射关系。
- 频次统计
- 使用字典来统计每个牌面出现的次数。一个牌面值出现的次数越多,我们就越有可能利用它来组成“葫芦”。
- 构建候选葫芦
- 遍历所有可能的牌面组合,检查是否能构成“葫芦”(即出现频次至少为 3 的牌面和频次至少为 2 的牌面),并计算其总和,确保总和不超过 max。
- 排序与输出
- 对于符合条件的“葫芦”,优先比较三张相同牌的大小,如果三张相同牌相同,则再比较两张相同牌的大小,最终输出符合条件的最大“葫芦”。
步骤:
- 对输入的牌面数组进行频次统计。
- 生成所有可能的“葫芦”组合(即三张相同和两张相同的牌面),并计算总和。
- 遍历所有合法组合,选择最大的一个。
代码实现:
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)
解释:
- get_card_value(card)
- 这个函数将牌面值(比如 'A', 'K', 'Q', 'J', '10', '9', ..., '2')映射为对应的数值。
- find_best_full_house(n, max_sum, array)
- 这个函数是核心部分,首先统计所有牌面出现的次数,然后生成符合条件的“葫芦”,并通过排序来选择最大的组合。
- 排序
- 首先根据三张相同的牌(a)的大小排序,如果相同,再根据两张相同的牌(b)的大小排序。
- 输出
- 如果找到符合条件的“葫芦”,输出其 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,可以跳过不符合要求的组合。