题目描述
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子.....LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
解法一:
排除法,排除所有错误情况,就是顺子
- 排除数组长度不为5的情况
- 排除小于0或者大于13的情况
- 排除5个0的情况(因为只有4个0)
- 排除数组范围大于4的情况。对于这里说明一下,如果是扑克牌顺子,数组范围肯定是小于等于4的。 这里具体来说分两种情况,一种是不会超过13的顺序,例如[1,2,3,4,5],可以用公式numbers[4] - numbers[i] <=4表示,i为第一个不为0的数的下标;另一种是超过13的顺序,例如[1,2,11,12,13],可以采用10以下的数字全部加上13,然后5个新数重排,再执行上边的公式即可。当然这是自己的想法,会比较麻烦。
- 最后排除对子即可
对于这道题,我觉得第三步的第二种情况也是顺子,可能个人理解略有偏颇,望大牛不吝指教。
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
int length = numbers.size();
//固定牌数为5
if (length != 5)
return false;
sort(numbers.begin(), numbers.end());
int i = 0, n = 0;
if (numbers[0] < 0 || numbers[4] > 13)
return false;
while (numbers[i] == 0)
{
i++;
n++;
}
//排除5个0的情况
if (n == 5)
return false;
//固定范围为4,超过4则不可能组成顺子
if (numbers[4] - numbers[i] > 4)
{
vector<int> vec;
int j;
for (j = 0; j < 5; j++)
{
if (numbers[i] < 10)
vec.push_back(numbers[j] + 13);
else
vec.push_back(numbers[j]);
}
sort(vec.begin(), vec.end());
if (vec[4] - vec[0] > 4)
return false;
}
//排除对子
while(i+1 < 5)
{
if (numbers[i] == numbers[i+1])
return false;
i++;
}
return true;
}
};
解法二(不存在超出13的顺子):
- 计算间距,比较0的个数和非连续间距的值即可
- 或者计算最大值与最小值的插值是否大于4,只要4之内,排除对子,就可构成顺子
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
int length = numbers.size();
//固定牌数为5
if (length != 5)
return false;
sort(numbers.begin(), numbers.end());
if (numbers[0] < 0 || numbers[4] > 13)
return 0;
int i = 0, n = 0, dec = 0;
while (numbers[i] == 0)
{
i++;
n++;
}
if (n > 4)
return false;
if (numbers[4] - numbers[i] > 4)
return false;
for (int j = i; j < 4; j++)
{
if (numbers[j] == numbers[j + 1])
return false;
}
return true;
}
};
解法三(来源牛客):
- 利用位来做存储,对于我这种小白来说,很新颖的思路
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
int length = numbers.size();
//固定牌数为5
if (length != 5)
return false;
int min = 14;
int max = -1;
int flag = 0;
for(int i = 0; i < length; i++) {
int number = numbers[i];
if(number < 0 || number > 13) return false;
if(number == 0) continue;
//排除对子
if(((flag >> number) & 1) == 1) return false;
flag |= (1 << number);
if(number > max) max = number;
if(number < min) min = number;
if(max - min >= 5) return false;
}
return true;
}
};
曾经在编程珠玑第一章就见过用位图的,由于技术较渣,所以决定以后再看。
后边有时间会补充关于位图的知识。