面试题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; } };
-----------------------------------
心之所向,素履所往;生如逆旅,一苇以航。
------------------------------------------