《剑指Offer》面试题:扑克牌的顺子

题目描述

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决定去买体育彩票啦。

思路

将数组中的数进行排序,然后检测从第一个非零数开始统计之间的间隔数的个数是否小于等于0的个数,如果满足,则是顺子
排序,在这里选择快排进行排序。
有一点疑问的地方:12 、13 1 2 3这样的是不是顺子(即首尾相连的是不是顺子)。//在此程序中并没有考虑这种情况。

/*

现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何。为了方便起见,你可以认为大小王是0。
输入:
输入有多组数据。
每组数据包含两行,第一行输入一个正数n(0<=n<=14),表示从扑克牌中抽出的扑克牌数。接下来的一行输入n个数,表示从这幅扑克牌中抽出的牌。如果n=0,则结束输入。
输出:
对应每组数据,如果抽出的牌是顺子,则输出“So Lucky!”。否则,输出“Oh My God!”。
样例输入:
5
3 5 1 0 4
5
3 5 4 7 6
5
3 5 7 4 8
0
样例输出:
So Lucky!
So Lucky!
Oh My God!
*/

#include<stdio.h>
#include<stdlib.h>
void swap(int *a,int *b){
    if(a!=NULL&&b!=NULL){
        int temp=*a;
        *a=*b;
        *b=temp; 
    }
}
/*
参数的说明
@param arr:原数组
@param begin:数组中的起始下标
@param end:数组中可以访问到的最后一个下标。 
*/ 
int partition(int *arr,int begin,int end){
    if(arr==NULL||begin>end){
        return -1;
    }
    //选取第一个元素为主元
    int index=begin;
    for(int i=begin+1;i<=end;i++){//刚开始,for循环中 写的 i<end;导致快排不正确。 
        if(arr[i]<arr[begin]){
            index++;
            swap(&arr[index],&arr[i]);
        } 
    }
    swap(&arr[begin],&arr[index]) ;
    return index;
}
/*
参数的说明
@param arr:原数组
@param begin:数组中的起始下标
@param end:数组中可以访问到的最后一个下标。 
*/
void quickSort(int *arr,int begin,int end){
    if(arr==NULL||begin>end){
        return;
    }
    if(begin<=end){
        int q=partition(arr,begin,end);
        quickSort(arr,begin,q-1);
        quickSort(arr,q+1,end);
    }
}
bool isOrder(int *arr,int len){
    bool isOrder=false;
    if(arr==NULL||len<2){
        return isOrder;
    }
    //利用快排对arr进行排序 
    quickSort(arr,0,len-1);
    //排序后的结果:为方便观察下快排是否写的正确。 
//  for(int i=0;i<len;i++){
//      printf("%d ",arr[i]);
//  } 
//  printf("\n");
    int countZero=0;//用来统计数组中零的个数 
    int count=0;//用来统计数组中非零数之间的间隔总数 
    for(int i=0;i<len;i++) {
        if(arr[i]==0){//统计数组中有几个0元素,即牌中有几个大小王 
            countZero++;
        }
        if(arr[i]!=0&&i!=len-1){//用来统计数组中非零数之间的间隔总数,从第一个非零的数开始统计 
            //需要考虑是否有相等的两个数,若存在,则不可能为顺子
            int tempCount= (arr[i+1]-arr[i]-1);
            if(tempCount<0){
                return false;
            }
            else{
                count+=tempCount ;
            }

        } 
    }
    if(count<=countZero){
        isOrder=true;
    }
    return isOrder;



}
int main(void){
    int n;
    while(scanf("%d",&n)!=EOF){
        if(n==0)
            break;
        if(n>0){
            int *arr=(int *)malloc(n*sizeof(int));
            if(arr==NULL){
                exit(EXIT_FAILURE);
            }
            int val;
            for(int i=0;i<n;i++){
                scanf("%d",&val);
                arr[i]=val;
            }
            bool result=isOrder(arr,n);
            if(result){
                printf("So Lucky!\n");
            }
            else{
                printf("Oh My God!\n");
            }
        }
    }
    return 0;
} 

你可能感兴趣的:(快排,扑克牌,顺子)