题解 | #扑克牌顺子#
扑克牌顺子
https://www.nowcoder.com/practice/762836f4d43d43ca9deb273b3de8e1f4
扑克牌顺子:最直观的想法是,首先想想顺子的特点是什么。首先顺子中不能出现相同的元素,其次顺子中各元素相差值为1,如果相差值大于1,可以使用万能牌0进行补齐,同时要考虑元素之间相差值过大从而导致万能牌无法补齐的情况。具体做法如下:首先对数组进行排序,然后统计数组中0出现的次数,即可用的万能牌张数,接着遍历剩余非0元素,如果剩余元素出现相等情况,则直接返回false,即不能构成顺子,反之统计元素之间的差值,注意,此处的差值是大于正常差值1的差值,最后根据万能牌的张数与元素之间的差值比较来判断返回true还是false。
bool IsContinuous( vector<int> numbers )
{
// 首先对numbers数组进行排序
sort(numbers.begin(),numbers.end());
// 统计数组中0出现的个数
int i=0; //i表示下标
int zero_num=0; //zero_num表示0的个数
while(numbers[i]==0) //i++放在循环条件中会导致数组异位
{
zero_num++;
i++;
}
// 遍历数组统计元素间隔
int interdiff=0; //interdiff表示元素间隔值
for(;(i+1)<numbers.size();i++)
{
// 如果出现相等元素则不能构成顺子
if(numbers[i+1]==numbers[i])
return false;
// 正常的顺子元素两者之间间隔为1 其余则是补万能牌
interdiff+=(numbers[i+1]-numbers[i]-1);
}
// 如果功能牌可以补齐差值则返回true反之为false
return zero_num>=interdiff?true:false;
}
idea:既然不能出现重复元素,那么可以使用集合uset来进行处理。具体做法如下:遍历数组,如果遇到0则直接跳过,反之查找uset中是否包含该元素,如果包含则表明出现了重复元素,直接返回false,反之将该元素加入uset中,然后分别统计数组中的最大值和最小值,最后根据最大值和最小值的差值是否超过5来判断返回true还是返回false。
bool IsContinuous( vector<int> numbers )
{
// 集合 用于存储除0外的非重复元素
unordered_set<int> uset;
// 统计最大值 最小值 数值范围1~14
int maxn=-1,minx=15;
// 遍历数组元素
for(int i=0;i<numbers.size();i++)
{
// 如果遇到0则跳过
if(numbers[i]==0)
continue;
// 遇到相同元素则返回false
if(uset.find(numbers[i])!=uset.end())
return false;
// 反之加入set
else uset.emplace(numbers[i]);
// 统计非0最大值
maxn=max(maxn,numbers[i]);
// 统计非0最小值
minx=min(minx,numbers[i]);
}
// 如果最大值与最小值相差不超过5则一定可以构成顺子
return (maxn-minx+1)<=5?true:false;
}
#扑克牌顺子#剑指offer 文章被收录于专栏
剑指offer专栏主要分享剑指offer题解。

查看14道真题和解析