题目
从扑克牌中随机抽5张牌,判断是不是一个顺子, 即这5张牌是不是连续的。2~10为数字本身, A为1。 J为11、Q为12、 为13。小王可以看成任意数字。
思路
接下来我们分析怎样判断5个数字是不是连续的,最直观的方法是把数组排序。值得注意的是,由于0可以当成任意数字,我们可以用0去补满数组中的空缺。如果排序之后的数组不是连续的,即相邻的两个数字相隔若干个数字,但只要我们有足够的。可以补满这两个数字的空缺,这个数组实际上还是连续的。举个例子,数组排序之后为{0,1,3,4,5}在1和3之间空缺了一个2,刚好我们有一个0,也就是我们可以把它当成2去填补这个空缺。
- 首先把数组排序
- 再统计数组中0 的个数
- 最后统计排序之后的数组中相邻数字之间的空缺总数。如果空缺的总数小于或者等于0 的个数,那么这个数组就是连续的:反之则不连续。
如果数组中的非0 数字重复出现,则该数组不是连续的。换成扑克牌的描述方式就是如果一副牌里含有对子,则不可能是顺子。
#include <iostream> #include <algorithm> #include <vector> using namespace std; class Solution { public: bool is_continuous(vector<int> num); //要求函数对象,或是静态/全局函数指针 //非静态成员函数指针不能直接传递给std::sort,因为成员函数默认有this指针,这样和sort函数所需的排序 //类型不一样。 static bool cmp(const int &a,const int &b); }; bool Solution::cmp(const int &a,const int &b) { return a<=b; } bool Solution::is_continuous(vector<int> num) { if(num.empty()||num.size()<1) return false; sort(num.begin(),num.end(),Solution::cmp); int num_of_zero=0; for(int i=0;i<num.size()&&num[i]==0;++i) ++num_of_zero; int small=num_of_zero; int big=small+1; int num_of_grap=0; while(big<num.size()) { if(num[small]==num[big])//有对子就不可能有顺子 return false; num_of_grap+=num[big]-num[small]-1; small=big; ++big; } return num_of_zero>=num_of_grap?true:false; } int main() { Solution s; vector<int> num{0,1,3,4,5}; cout<<boolalpha<<s.is_continuous(num)<<endl; return 0; }
code2
class Solution { public: bool IsContinuous( vector<int> num ) { if(num.size()<5) return false; sort(num.begin(),num.end()); int gap=0; int k=0; for(int i=0;i<num.size()-1;++i) { if(num[i]==0) { ++k; continue; } if(num[i]==num[i+1]) return false; else gap+=(num[i+1]-num[i]-1); } return gap<=k?true:false; } };