【剑指offer】:扑克牌的顺序

版权声明:本文为博主原创文章,欢迎转载,转载请声明出处! https://blog.csdn.net/hansionz/article/details/82694214

题目:从扑克牌中随机抽取5张牌,判断是不是一个顺子,既这5张牌是不是连续的。2-10位数字本身A为1,J为11,Q为12,K为13大王和小王可以看出是任何数

解决思路:

  • 1.把大王和小王看做是0
  • 2.对所给序列进行排序
  • 3.统计差值的个数(如果相邻的两个值差1,则差值为0,如果差大于1,则插入为n-1)
  • 4.统计0的个数
  • 5.比较。如果差值的个数大于0,则必然不是顺子,否则是顺子

代码实现:

#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
//直接插入排序
int InsertSort(int *num, int len)
{
    assert(num);
    int i = 0;
    //第一个元素已经为有序序列,所以要进行len-1次排序
    for (; i < len - 1; i++)
    {
        int end = i;
        int tmp = num[i + 1];//保存非有序区间第一个元素,否则在后边的移动中会改变
        //比较后移
        while (end >= 0 && num[end]>tmp)
        {
            num[end + 1] = num[end];
            --end;
        }
        //插入到适当位置
        num[end + 1] = tmp;
    }
}
int Compare(const void* arg1, const void* arg2)
{
    return *(int*)arg1 - *(int*)arg2;
}
//判断是否为一个顺子(是返回1,不是返回0)
int CheckContiuos(int *num, int len)
{
    assert(num);
    if (len <= 0)
        return 0;
    //1.排序
    /*InsertSort(num, len);*/
    //直接调用库函数qsort(时间复杂度为O(nlogn))
    qsort(num, len, sizeof(int), Compare);
    //0代表大小王,可以随意替换
    int number_zero = 0;//记录0的个数
    //2.统计0的个数
    for (int i = 0; i < len; i++)
    {
        if (num[i] == 0)
            ++number_zero;
    }
    //3.统计差值的个数
    int number_gap = 0;//记录差值的个数
    int low = number_zero;//非0第一个值的下标
    int high = low + 1;//low后边那个值得下标,为了计算差值
    while (high < len)
    {
        //如果存在对子,绝对不是对子
        if (num[low] == num[high])
            return 0;
        //每个相邻的数间隔1是正常的,多出来的就算差值
        number_gap += num[high] - num[low] - 1;
        low++;//继续向后查找
        high++;
    }
    //差值的个数如果比0的个数多,则肯定不是顺子
    return (number_gap > number_zero) ? 0 : 1;
}
int main()
{
    int num[] = { 1, 2, 3, 6, 6, 0, 0 };
    int len = sizeof(num) / sizeof(num[0]);
    int ret = CheckContiuos(num, len);
    printf("%d\n", ret);
    return 0;
}

注意:排序可以采用不同的做法,如果要效率高的话,也可以考虑用哈希表做,上边的代码是用的是插入排序和直接调用库函数qsort。

猜你喜欢

转载自blog.csdn.net/hansionz/article/details/82694214
今日推荐