面试题61:扑克牌中的顺子(C++)

题目地址:https://leetcode-cn.com/problems/bu-ke-pai-zhong-de-shun-zi-lcof/

题目描述

从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。

题目示例

示例 1:

输入: [1,2,3,4,5]
输出: True

示例 2:

输入: [0,0,1,2,5]
输出: True

解题思路

构成顺子条件:

  • 除大小王之外,其余牌数均未出现重复的情况,可通过判断数组相邻元素解决;
  • 5张牌中的最大牌 - 最小牌 < 5(大小王除外)

思路1:简单排序。我们首先对拿到的数组nums进行排序,这样扑克牌就有序了,然后思考构成顺子的条件,我们发现可以通过大小王的张数来判断,即两张牌之间需要多少张大小王来填补,因为大小王0可代表任何牌数,所以可填充顺子中缺少的数,如果需要填补的大小王数量小于或等于已有大小王的张数,则表示能够构成顺子,返回true,否则,不能构成顺子,返回false。例如,扑克牌顺序0,0,1,5,6;其中,扑克牌1和扑克牌5之间需要5-1=4张大小王来填补,但扑克牌中却只有两张大小王(即两个0),所以它不能构成顺子。

思路2:对思路1进行优化,数组排序之后,可得5张牌中的最大牌,以及最小牌(大小王除外),若最大牌 - 最小牌 < 5,则可构成顺子,返回true,否则,不能构成顺子,返回false。

思路3:哈希表。使用哈希表判断除0之外是否有重复的牌数,如果没有,则判断(最大牌数 - 最小牌数)是否小于5,若小于,则构成顺子,返回true,否则,表示不能构成顺子,返回false。

程序源码

排序

class Solution {
public:
    bool isStraight(vector<int>& nums) {
        if(nums.size() == 0) return false;
        int cnt = 0; //统计大小王个数
        sort(nums.begin(), nums.end()); //数组排序,便于发现重复元素
        for(int i = 0; i < nums.size() - 1; i++)
        {
            if(nums[i] == 0) 
                cnt++; //大小王个数统计
            else if(nums[i] == nums[i + 1]) 
                return false; //除过大小王为0重复外,其余重复均不能构成顺子,返回false
            else
                cnt -= (nums[i + 1] - nums[i] - 1); //相邻两张牌之间需要多少张大小王
        }
        return cnt >= 0; //构成顺子条件:大小王张数大于等于相邻两张牌之间的牌数
    }
};

排序优化(最大值 - 最小值 < 5)

case1:

class Solution {
public:
    bool isStraight(vector<int>& nums) {
        if(nums.size() == 0) return false;
        sort(nums.begin(), nums.end());
        int cnt = 0; //统计大小王个数
        for(int i = 0; i < nums.size() - 1; i++)
        {
            if(nums[i] == 0) cnt++; //大小王张数
            if(nums[i + 1] == nums[i] && nums[i] != 0) return false;
        }
        return nums[4] - nums[cnt] < 5; //5张牌构成顺子条件:最大牌 - 最小牌 < 5
    }
};

case2:

class Solution {
public:
    bool isStraight(vector<int>& nums) {
        if(nums.size() == 0) return false;
        sort(nums.begin(), nums.end());
        for(int i = 0; i < nums.size() - 1; i++)
        {
            if(nums[i] != 0)
            {
                if(nums[i] == nums[i + 1]) return false;
                if(nums[4] - nums[i] >= 5) return false;
            }
        }
        return true;
    }
};

哈希表

class Solution {
public:
    bool isStraight(vector<int>& nums) {
        if(nums.size() == 0) return false;
        unordered_map<int, bool> joker_num;
        int max_joker = -1, min_joker = 14;
        for(int num:nums)
        {
            if(num!=0) 
            {
                if(joker_num.find(num) != joker_num.end()) return false;
                joker_num[num]=true;
                max_joker = max(max_joker, num);
                min_joker = min(min_joker, num);
            }
        }
        return max_joker - min_joker < 5;
    }
};
----------------------------------- 心之所向,素履所往;生如逆旅,一苇以航。 ------------------------------------------
原文地址:https://www.cnblogs.com/wzw0625/p/12860165.html