扑克牌的顺子
题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这五张牌是不是连续的.2~10为数字本身,A为1,J为11,Q为12,K为13,而大小王可以为任意数字.
我们需要把扑克牌的背景抽象成计算机语言。不难想象,我们可以把5张牌看成由5个数字组成的数组。大小王是特殊的数字,我们不妨把他们都定义为0,这样就能和其他牌区分开来了。
接下来我们分析怎样判断5个数字是不是连续的,最直观的方法是把数组排序.值得注意的是,由于0可以当成任意数字,我们可以用0去补满数组中的空缺.如果排序之后的数组是不连续的,即相邻的两个数字相隔若干个数字,但只要我们有足够的0可以填满这两个数字的空缺,这个数组实际上还是连续的。举个例子,数组排序之后为{0,1,3,4,5},在1和3之间空缺了一个2,刚好我们有一个0,也就是我们可以把它当成2去填补这个空缺。
于是我们需要做3件事情:首先把数组排序,再统计数组中0的个数,最后统计排序之后的数组中相邻数字之间的空缺总数。如果空缺总数小于或者等于0的个数,那么这个数组就是连续的;反之则不连续.
最后,我们还需要注意一点:如果数组中的非0数字重复出现,则该数组不是连续的.换成扑克牌的描述方式就是如果一幅牌里含有对子,则不可能是顺子.
基于这个思路,我们可以写出如下代码:
1 bool IsContinous(int* numbers,int length) 2 { 3 if(numbers==NULL||length<1) 4 return false; 5 qsort(numbers,length,sizeof(int),compare); 6 int numberOfZero=0; 7 int numberOfGap=0; 8 9 //统计数组中0的个数 10 for(int i=0;i<length&&numbers[i]==0;++i) 11 ++numberOfZero; 12 13 //统计数组中的间隔数目 14 int small=numberOfZero; 15 int big=small+1; 16 while(big<length) 17 { 18 //如果两个数相等,有对子,不可能是顺子 19 if(numbers[small]==numbers[big]) 20 return false; 21 22 numberOfGap +=number[big]-number[small]-1; 23 small=big; 24 ++big; 25 } 26 return (numberOfGap>numberOfZero) ? false : true; 27 } 28 29 int compare(const void *arg1,const void * arg2) 30 { 31 return *(int*)arg1 - *(int*)arg2; 32 } 33