从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。
组成顺子有一些条件是必须要满足的,
1.除了大小王之外, 其他牌不能重复
2.除了大小王之外, 最大值-最小值==4(没有零), 最大值-最小值==3或4(有1个零), 最大值-最小值==2或3或4(有2个零) , 但是看到了别人的优化版, 这几种情况可以统一为 最大值-最小值<5即可, 不需要看0个数量
tip : 使用set可以方便的查看数组中是否有重复,
第一个算法是分开验证2个条件, 更有助于理解 , 第二个算法优化了判断方法,效率更高
func isStraight(_ nums: [Int]) -> Bool {
var numberOfKing = 0
var maxValue = 0
var minValue = 100
for num in nums {
if num == 0 {
numberOfKing += 1
}
if num>maxValue {
maxValue = num
}
if num<minValue && num != 0 {
minValue = num
}
}
// 最大值-最小值 >= 5 肯定不可以, 比如34568
if maxValue-minValue >= nums.count {
return false
}
// 把数组转成set,利用set查看是否有重复, 检查除0以外有没有重复
var result = Set(nums)
result.remove(0)
// 小于说明非0数字 有重复
if result.count < nums.count - numberOfKing {
return false
}
// 到这里, 说明是无重复 && 最大值-最小值<=4, 剩余的可以用0补齐
return true
}
目前来看最优解是下面这个, 同时把第一步和第二步判断了, 只需要遍历一次即可
// 优化版
func isStraight2(_ nums: [Int]) -> Bool {
var maxValue = 0
var minValue = 100
var set = Set<Int>()
for num in nums {
if num == 0 {
continue
}
if num>maxValue {
maxValue = num
}
if num<minValue {
minValue = num
}
// 如果有重复, 不可以
if set.contains(num) {
return false
} else {
set.insert(num)
}
}
// 最大值-最小值>=5, 比如12346,肯定是不可以的
if maxValue-minValue >= nums.count {
return false
}
// 到这里, 说明是无重复, 最大值-最小值<=4
return true
}