最好的扑克手牌

标签: 数组 哈希表 计数

难度: Easy

给你一个整数数组 ranks 和一个字符数组 suit 。你有 5 张扑克牌,第 i 张牌大小为 ranks[i] ,花色为 suits[i] 。

下述是从好到坏你可能持有的 手牌类型 

  1. "Flush":同花,五张相同花色的扑克牌。
  2. "Three of a Kind":三条,有 3 张大小相同的扑克牌。
  3. "Pair":对子,两张大小一样的扑克牌。
  4. "High Card":高牌,五张大小互不相同的扑克牌。

请你返回一个字符串,表示给定的 5 张牌中,你能组成的 最好手牌类型 。

注意:返回的字符串 大小写 需与题目描述相同。

示例 1:

输入:ranks = [13,2,3,1,9], suits = ["a","a","a","a","a"]
输出:"Flush"
解释:5 张扑克牌的花色相同,所以返回 "Flush" 。

示例 2:

输入:ranks = [4,4,2,4,4], suits = ["d","a","a","b","c"]
输出:"Three of a Kind"
解释:第一、二和四张牌组成三张相同大小的扑克牌,所以得到 "Three of a Kind" 。
注意我们也可以得到 "Pair" ,但是 "Three of a Kind" 是更好的手牌类型。
有其他的 3 张牌也可以组成 "Three of a Kind" 手牌类型。

示例 3:

输入:ranks = [10,10,2,12,9], suits = ["a","b","c","a","d"]
输出:"Pair"
解释:第一和第二张牌大小相同,所以得到 "Pair" 。
我们无法得到 "Flush" 或者 "Three of a Kind" 。

提示:

  • ranks.length == suits.length == 5
  • 1 <= ranks[i] <= 13
  • 'a' <= suits[i] <= 'd'
  • 任意两张扑克牌不会同时有相同的大小和花色。

Submission

运行时间: 22 ms

内存: 16.0 MB

# class Solution:
#     def bestHand(self, ranks: List[int], suits: List[str]) -> str:
#         if len(set(suits))==1: #先判断花色相同
#             return 'Flush'
#         cnt = [0]*14 
#         for r in ranks:
#             cnt[r]+=1
#         return ['High Card','Pair','Three of a Kind','Three of a Kind'][max(cnt)-1] #题目明确规定没有相同牌,max(cnt)最多就是4,不会出界

class Solution:
    def bestHand(self, ranks: List[int], suits: List[str]) -> str:
        if len(set(suits))==1:
            return "Flush"
        h=Counter(ranks)
        if len(h)==5:
            return "High Card"
        for [a,b] in h.items():
            if b>2:
                return "Three of a Kind"
        return "Pair"

Explain

此题解首先检查是否所有牌具有相同的花色,如果是,则直接返回'Flush',因为这是最好的手牌类型。若不是同花,则利用Counter来统计每个等级(rank)的牌出现的次数。首先判断如果有五种不同的rank,那么它必定是'High Card'。然后,遍历Counter中的键值对,检查是否存在出现次数大于2的牌,如果有,则返回'Three of a Kind'。如果上述条件都不满足,则表明至少有一对,返回'Pair'。

时间复杂度: O(1)

空间复杂度: O(1)

# class Solution:
#     def bestHand(self, ranks: List[int], suits: List[str]) -> str:
#         if len(set(suits)) == 1:  # 检查是否所有牌具有相同的花色
#             return 'Flush'  # 是同花
#         rank_count = Counter(ranks)  # 统计每个等级的牌的数量
#         if len(rank_count) == 5:
#             return 'High Card'  # 如果有五种不同的等级,返回高牌
#         for rank, count in rank_count.items():
#             if count > 2:
#                 return 'Three of a Kind'  # 如果有任何等级的牌出现超过两次,返回三条
#         return 'Pair'  # 否则,至少有一对

Explore

在Python中,可以通过创建花色的集合(set)来判断所有牌是否具有相同的花色。如果所有的牌都是同一花色,那么这个集合的大小(len)应该为1。例如,将所有牌的花色放入一个集合中,如果集合的长度为1,说明没有任何花色的不同,所有牌都是同一花色,因此返回'Flush'。

在扑克牌中,'High Card'意味着没有任何更好的组合,只能依据单张牌的大小来比较。如果有五种不同的rank,则没有任何的对子、三条或其他任何类型的组合,因此是'High Card'。如果其中有两张或更多的牌rank相同,那么这不再是'High Card',而是至少是'Pair'或更高级别的手牌。因此,只有当所有五张牌的rank都不相同时,才满足'High Card'的条件。

在判断'Three of a Kind'时,会检查Counter对象中是否有任何rank的数量超过2。只有当一个rank的计数值超过2时,才会返回'Three of a Kind'。如果只有两张牌rank相同,那么最大的计数值为2,这种情况下不会返回'Three of a Kind',而是继续检查是否至少有一对,从而可能返回'Pair'。

在这种解法中,逻辑是尽快地确定手牌的最好可能性。'Three of a Kind'是比'Pair'或'High Card'更强的手牌。因此,如果发现有三张相同rank的牌,可以立即断定这是最好的可能手牌(在没有'Flush'的情况下),无需进一步检查是否存在两对。这种做法简化了逻辑并提高了效率,因为一旦确定了更高级别的手牌,就无需考虑较低级别的可能性。