难度简单294
从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。
示例 1:
输入: [1,2,3,4,5]
输出: True示例 2:
输入: [0,0,1,2,5]
输出: True限制:
数组长度为 5
数组的数取值为 [0, 13]
解题思路:
一开始我的想法是去遍历这个数组去统计0的个数,然后再遍历一遍数组将非0的元素,结合0的个数进行判断,但是发现这个方法有点太复杂了,所以借鉴了题解,大概有两个方法,但是先来讲一下这道题的精髓之处!
这道题因为限制了元素个数为5个,并且要求是顺子,那么我们想一下,这五个数字必定是连续的,那么它的最大值和最小值的差,最大不能超过 5,但是可以小于 5。
为什么呢,因为先举个例子:1,2,3,4,5 这五个元素其中不含0,所以它们的最大差值就是 5 - 1 也就是 4,但是如果含 0,比如说 0,0,3,4,5 这组元素,那么其中不包括 0 的最大差值就是 5 - 3 为 2,同样是成立的,因为我们不需要去考虑 0,0 是万能的,所以我们只需要判断非 0 元素的最大差值即可,除此之外还需要判断一下是否存在非 0 元素之间重复,是的话直接 false!
总结起来就是:Max - Min(非0的最小值) < 5
下面给出基于上述结论的两种实现方法:
1、set判重 + 记录最值
class Solution {
public:
bool isStraight(vector<int>& nums) {
set<int> st;
int Max = INT_MIN, Min = INT_MAX;
for(int i = 0; i < nums.size(); ++i)
{
// 不考虑0的情况,因为0万能
if(nums[i] == 0)
continue;
// 有重复的直接false
if(st.count(nums[i]))
return false;
st.insert(nums[i]);
// 记录最值
Max = max(Max, nums[i]);
Min = min(Min, nums[i]);
}
return Max - Min < 5;
}
};2、排序 + 相邻元素判重
其中 nums[zeroNum] 代表的就是排序数组中第一个非0元素,即最小值!
class Solution {
public:
bool isStraight(vector<int>& nums) {
int zeroNum = 0;
// 排序后,最后一个元素为最大值,只需要找到第一个非0元素即可
sort(nums.begin(), nums.end());
for(int i = 0; i < nums.size() - 1; ++i)
{
if(nums[i] == 0)
{
zeroNum++;
continue;
}
// 发现重复的直接false
if(nums[i] == nums[i + 1])
return false;
}
// 最大牌 - 最小牌(非0的最小)< 5 则为顺子
return nums[nums.size() - 1] - nums[zeroNum] < 5;
}
};