本文最后更新于:2020年11月17日 下午
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张拍是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为0,可以看成任意数字。A不能视为14。
限制:
数组长度为5
数组的数取值为[0,13]。
class Solution:
def isStraight(self, nums):
解题思路:
根据题意,此5张牌是顺子的充分条件如下:
- 除大小王外,所有牌无重复;
- 设此5张牌中最大的牌为$max$,最小的牌为$min$(大小王除外),则需满足:
因此可将问题转化为:此5张牌是否满足以上条件?
方法一:集合Set+遍历
- 遍历五张牌,遇到大小王(即0)直接跳过。
- 判别重复:利用Set实现遍历判重,Set的查找方法的时间复杂度为$O(1)$;
- 获取最大/最小的牌:借助辅助变量$ma$和$mi$,遍历统计即可。
复杂度分析:
- 时间复杂度$O(1)$:本题中给定牌数量$N=5$;遍历数组使用$O(N)=O(5)=O(1)$时间。
- 空间复杂度$O(1)$:勇于判重的辅助Set使用$O(N)=O(1)$额外空间。
class Solution:
def isStraight(self, nums):
repeat = set()
ma, mi = 0, 14
for num in nums:
if num == 0: continue # 跳过大小王
ma = max(ma, num) # 最大牌
mi = min(mi, num) # 最小牌
if num in repeat: return False # 若有重复,提前返回false
repeat.add(num)
return ma - mi < 5
方法二:排序+遍历
- 先对数组执行排序。
- 判别重复:排序数组中的相同元素位置相邻,因此可通过遍历数组,判断$nums[i]=nums[i+1]$是否成立来判重。
- 获取最大/最小的牌:排序后,数组末位元素$nums[4]$为最大牌;元素$nums[joker]$为最小牌,其中$joker$为大小王的数量。
复杂度分析:
- 时间复杂度$O(1)$:本题中给定牌数量$N=5$;数组排序使用$O(NlogN)=O(5log5)=O(1)$时间。
- 空间复杂度$O(1)$:变量$joker$使用$O(1)$大小的额外空间。
class Solution:
def isStraight(self, nums):
joker = 0
nums.sort() # 数组排序
for i in range(4):
if nums[i] == 0: joker += 1 #统计大小王数量
elif nums[i] == nums[i+1]: return False # 若有重复,提前返回false
return nums[4] - nums[joker] < 5 # 最大牌 - 最小牌 < 5则可构成顺子
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!