扑克牌顺子

题目描述

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决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。

解法一:

      排除法,排除所有错误情况,就是顺子

  1. 排除数组长度不为5的情况
  2. 排除小于0或者大于13的情况
  3. 排除5个0的情况(因为只有4个0)
  4. 排除数组范围大于4的情况。对于这里说明一下,如果是扑克牌顺子,数组范围肯定是小于等于4的。 这里具体来说分两种情况,一种是不会超过13的顺序,例如[1,2,3,4,5],可以用公式numbers[4] - numbers[i] <=4表示,i为第一个不为0的数的下标;另一种是超过13的顺序,例如[1,2,11,12,13],可以采用10以下的数字全部加上13,然后5个新数重排,再执行上边的公式即可。当然这是自己的想法,会比较麻烦。
  5. 最后排除对子即可

对于这道题,我觉得第三步的第二种情况也是顺子,可能个人理解略有偏颇,望大牛不吝指教。

class Solution {
public:
    bool IsContinuous( vector<int> numbers ) {
        int length = numbers.size();
        //固定牌数为5
        if (length != 5)
            return false;
        
        sort(numbers.begin(), numbers.end());
        int i = 0, n = 0;
        if (numbers[0] < 0 || numbers[4] > 13)
            return false;
        while (numbers[i] == 0) 
        {
            i++;
            n++;
        }
        //排除5个0的情况
        if (n == 5)
            return false;
        //固定范围为4,超过4则不可能组成顺子
        if (numbers[4] - numbers[i] > 4)
        {
            vector<int> vec;
            int j;
            for (j = 0; j < 5; j++)
            {
                if (numbers[i] < 10)
                    vec.push_back(numbers[j] + 13);
                else
                    vec.push_back(numbers[j]);
            }
            sort(vec.begin(), vec.end());
            if (vec[4] - vec[0] > 4)
                return false;
        }
        //排除对子
        while(i+1 < 5)
        {
            if (numbers[i] == numbers[i+1])
                return false;
            i++;
        }
        return true;
    }
};

解法二(不存在超出13的顺子):

  •  计算间距,比较0的个数和非连续间距的值即可
  •  或者计算最大值与最小值的插值是否大于4,只要4之内,排除对子,就可构成顺子
class Solution {
public:
    bool IsContinuous( vector<int> numbers ) {
        int length = numbers.size();
        //固定牌数为5
        if (length != 5)
            return false;
        
        sort(numbers.begin(), numbers.end());
        if (numbers[0] < 0 || numbers[4] > 13)
            return 0;
        int i = 0, n = 0, dec = 0;
        while (numbers[i] == 0)
        {
            i++;
            n++;
        }
        if (n > 4)
            return false;
        
        if (numbers[4] - numbers[i] > 4)
            return false;
        
        for (int j = i; j < 4; j++)
        {
            if (numbers[j] == numbers[j + 1])
                return false;
        }
        
        return true;
    }
};

解法三(来源牛客):

  • 利用位来做存储,对于我这种小白来说,很新颖的思路
class Solution {
public:
    bool IsContinuous( vector<int> numbers ) {
        int length = numbers.size();
        //固定牌数为5
        if (length != 5)
            return false;
        
        int min = 14;
        int max = -1;
        int flag = 0;
        for(int i = 0; i < length; i++) {
            int number = numbers[i];
            if(number < 0 || number > 13) return false;
            if(number == 0) continue;
            //排除对子
            if(((flag >> number) & 1) == 1) return false;
            flag |= (1 << number);
            if(number > max) max = number;
            if(number < min) min = number;
            if(max - min >= 5) return false;
        }
        return true;
    }
};

曾经在编程珠玑第一章就见过用位图的,由于技术较渣,所以决定以后再看。

后边有时间会补充关于位图的知识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值