题解 | #扑克牌顺子#
扑克牌顺子
http://www.nowcoder.com/practice/762836f4d43d43ca9deb273b3de8e1f4
第一次思路: 对于每个元素x:
- 如果x == 0,则忽略;
- 如果x已经出现过,则false;
- 否则取其合理空间[x - 4, x + 4](遇到边界截取)
- 对每个元素的合理区间取交集,如果所有元素都在交集里,则合法,否则不能成为顺子
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
int i = 1, j = 13;
set<int> s;
for(int c = 0;c < numbers.size(); c ++){
if(numbers[c] == 0)
continue;
if(numbers[c] < i || numbers[c] > j)
return false;
if(!s.count(numbers[c]))
s.insert(numbers[c]);
else
return false;
i = numbers[c] > 4 ? ((numbers[c] - 4) > i ? (numbers[c] - 4) : i): (i > 1 ? i : 1);
j = numbers[c] < 10 ? ((numbers[c] + 4) < j ? (numbers[c] + 4) : j): (j < 13 ? j : 13);
}
return true;
}
};
改进1.0: 在第一次思路的基础上,不用合并区间,只用判断当前元素的极差(最大元素 - 最小元素)是否小于5即可
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
int min = 14, max = -1;
set<int> s;
for(int c = 0;c < numbers.size(); c ++){
if(numbers[c] == 0)
continue;
if(!s.count(numbers[c]))
s.insert(numbers[c]);
else
return false;
if(min > numbers[c])
min = numbers[c];
if(max < numbers[c])
max = numbers[c];
if(max - min >= 5)
return false;
}
return true;
}
};
改进2.0:
采用一个int整数代替set去执行判断牌是否重复
由于扑克牌是0-14的数字,而一个int数字有32位,我们可以使用int的低13位bit是否为1来判断这张牌是否已经出现过。
具体操作:
- flag&(1<<numbers[i])判断牌是否已经重复;
- flag|="(1<<numbers[i])标记此牌已经出现过;
class Solution {
public:
bool IsContinuous( vector<int> numbers ) {
int flag=0;//标记整数;
int _min=14,_max=0;
for(auto i:numbers){
if(i==0)continue;//大小王
_min=min(_min,i);//最小牌
_max=max(_max,i);//最大牌
if((flag&(1<<i))!=0)return false;//出现重复牌
flag|=(1<<i);
}
return _max-_min<5;//顺子中最大的牌点数max - 顺子中最小的牌点数min < 5
}
};