面试题61. 扑克牌中的顺子

题目: 从扑克牌中随机抽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
解释:1,2,5中间缺2个数,这时0有2个,万能,所以true

限制:数组长度为 5 ;数组的数取值为 [0, 13] 。


我们先理解一下什么是顺子:连续且不包含对子的5张牌。

(一)常规做法,根据元素大小判断顺子 O(N)

这个题目简单理解就是判断数字顺序,:

  • 首先对数组排序,因为题目给的是无序的。
  • 遍历数组,a[i]==0,表示万能牌,count++;
  • 判断a[i+1]-a[i]=1是否成立,成立表示顺序,不成立我们用万能牌补缺失的牌数,即count-a[i+1]-a[i]+1。
  • 判断是否a[i+1]-a[i]==0,表示出现了对子,直接返回false
  • 最后我们判断count<0吗,如果小于表示我们的万能牌不能弥补缺口,false;大于0表示万能牌可以。
bool isStraight(vector<int>& nums) 
{
	sort(nums.begin(), nums.end());//排序
	int count=0;
	for(int i=0;i<nums.size();i++)
	{
		if(nums[i]==0)//统计万能牌
		{
			count++;
			continue;
		}
		if(i<nums.size()-1)//用万能牌补充顺序缺口
		{
			if(nums[i+1]-nums[i]!=1)
				count-=(nums[i+1]-nums[i]-1);//进行补
			if(nums[i+1]-nums[i]==0)//出现对子,直接错误
			{
				return false;
			}
		}
	}
	if(count<0)//判断是否补够了
	{
		return false;
	}
	else
		return true;
}

(二)规律做法,根据牌数判断顺子 O(N)

我们先想一个事情,如果5张牌,最大数为6,最小数为2,那么需要几张牌才可以构成顺子,答案是2,3,4,5,6即6-2+1=5张牌,所以我们可以得出如果数组中最大数为m,最小数为n,那么构成顺子需要的牌数为m-n+1张。那么我们就可以通过牌数来判断是否可以构成顺子。

  • 首先我们找到最大值,最小值。
  • 计算所需牌数=最大值-最小值+1,如果所需牌数>5,表示不能构成顺子,false
  • 如果所需牌数<=5,表示可以构成,万能牌放在合适的位置上,true,因为我们已经拿最大值最小值判断了,所以肯定可以构成。
  • 还需要判断是否有一样的,一样的直接false,我们可以通过数组来标记,数组内容存储出现次数。
bool isStraight(vector<int>& nums) 
{
	int max=0,min=14;
	vector<int>same(14,0);//判断出现次数
	for(int i=0;i<nums.size();i++)
	{
		if(nums[i]==0)//不算万能牌
			continue;
		same[nums[i]]+=1;
		if(same[nums[i]]>1)//出现对子
			return false;
		
		max=max>nums[i]?max:nums[i];//最大值
		min=min<nums[i]?min:nums[i];//最小值
	}
	int count=max-min+1;
	if(count<=5)
		return true;
	else
		return false;
}

加油哦!🥘。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值