前言:剑指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,将扑克牌中的A、J、Q、K分别映射为数字1、11、12、13 - 然后,遍历输入的列表
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
执行结果如下图:
学到的知识点:
- 如何使用字典来存储和查找键值对,例如将扑克牌中的字母和数字对应起来
- 如何遍历列表中的元素,以及如何处理边界情况,例如重复的数字或列表为空