剑指 Offer 61. 扑克牌中的顺子

156 阅读2分钟

前言:剑指offer刷题系列

问题:

若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。

示例:

输入: [1,2,3,4,5]
输出: True

思路:

第一眼的思路就是:除了0以外,如果没有重复,最小值和最大值的差是4即为顺子。有0就需要考虑0的个数,没有,1个和2个。

  • 这个函数先定义一个字典mapping,将扑克牌中的AJQK分别映射为数字1111213
  • 然后,遍历输入的列表nums,如果其中有字母,则用字典中对应的数字替换,然后对列表进行排序,方便后续处理
  • 声明两个变量,zeros表示列表中有多少个零,即大小王,可以用来补充任意数字;gaps表示列表中有多少个间隔,即相邻两个数字之间的差值减一
  • 再次遍历列表,从第一个元素到倒数第二个元素:
    • 如果当前元素是零,则将zeros加一
    • 如果当前元素和下一个元素相等,则说明有重复的数字,直接返回False
    • 否则,计算当前元素和下一个元素之间的间隔,即两者相减再减一,将结果累加到gaps
  • 最后,判断zeros是否大于等于gaps,如果是,则说明可以用零来填补间隔,构成顺子;如果不是,则说明无法构成顺子,返回False

思考,代码如下:

class Solution:
    def isStraight(self, nums: List[int]) -> bool:
        mapping = {"A": 1, "J": 11, "Q": 12, "K": 13}
        for i in range(len(nums)):
            if nums[i] in self.mapping:
                nums[i] = self.mapping[nums[i]]
        nums.sort()
        zeros = 0
        gaps = 0
        for i in range(len(nums) - 1):
            if nums[i] == 0:
                zeros += 1
            elif nums[i] == nums[i + 1]:
                return False
            else:
                gap = nums[i + 1] - nums[i] - 1
                gaps += gap
        return zeros >= gaps

执行结果如下图:

image-20230911220403928.png

学到的知识点:

  • 如何使用字典来存储和查找键值对,例如将扑克牌中的字母和数字对应起来
  • 如何遍历列表中的元素,以及如何处理边界情况,例如重复的数字或列表为空