通过O(n)的效率判断是否为顺子及同花顺(C++)

通过O(n)的效率判断是否为顺子及同花顺

判断是否为顺子

TIPS:除去大小王,以及A和2分别对应14和15,即只有3,4,5,6,7,8,9,10,11(J),12(Q),13(K),14(A),15(2)。

效率需为O(n)

输入

{ 3,4,5,6,7 }
返回:true
{ 5,4,3,6,7 }
返回:true
{ 7,5,5,5,3 }
返回:false
{ 7,5,4,3,8 }
返回:false
{ 7 }
返回:true

方式一

设置两个标记位,最终分别指向最小的数和最大的数。同时设置一个容器用于处理重复出现的扑克(比如7 5 5 5 3),出现第二次5的时候直接返回false。

//判断是否为顺子
bool IsObedient(const vector<int>& arr)
{
	if (arr.empty())return arr.empty();
	int visited[16]{ 0 };//处理重复出现的数字
	int start = -1, end = -1;//标记位,分别指向最小的数和最大的数
	for (int i = 0; i < arr.size(); i++)
	{
        //过滤1,2两个数字
		if (arr[i] == 1 || arr[i] == 2)
			return false;
		if (start == -1 && end == -1)
		{
			start = arr[i];
			end = start;
		}
		else if (start > arr[i])
			start = arr[i];
		else if (end < arr[i])
			end = arr[i];
        //默认情况下visited最多只出现一次,如果已经出现了一次,那么说明重复出现了当前数,直接返回false。
		if (visited[arr[i]] == 1)
			return false;
		visited[arr[i]] = 1;
	}
	if (start == end || end - start == (arr.size() - 1))
		return true;
	return false;
}

方式二

遍历一次数据,将当前的数全部相加,求和值跟数据中间那位数(如果为偶数,那么为size/2-1的那位数)相除,如果结果等于当前数据总大小量,则是顺子,否则不是顺子。同时创建一个容器用于过滤重复的数字,与方式一相同。

bool IsObedient(const vector<int>& arr)
{
	if (arr.empty())return arr.empty();
	int visited[16]{ 0 };
	int res = 0;
	for (int i = 0; i < arr.size(); i++)
	{
		res += arr[i];
		if (visited[arr[i]] == 1)
			return false;
		visited[arr[i]] = 1;
	}
	if (arr.size() % 2 != 0 && res / arr[arr.size() / 2] == arr.size())
		return true;
	else if (arr.size() % 2 == 0 && res / arr[arr.size() / 2 - 1] == arr.size())
		return true;
	return false;
}

判断是否为同花顺

  我们使用一个字节表示扑克牌的花色以及大小(0000 0000),其中前四位分别为0,1,2,3表示黑红梅方(0000 0001 0010 0011),后四位代表扑克牌的大小。为了便于观察,我们使用十六进制进行记录,例如0x13表示花色为红桃3。

TIPS:

unsigned int b = 0x13;

获取值的方式:

int value = b & 0x0f;

判断花色并获得花色:

if((b & 0xf0) == 0x10)//红桃

{

​ //to do

}

//判断同花顺
bool IsCampaign(const vector<int>& arr)
{
	if (arr.empty())return arr.empty();
	enum Type
	{
		Hei = 0x00, //黑
		Hong = 0x10,//红
		Mei = 0x20,//梅
		Fang = 0x30,//方
		Kong,//空
	};
	bool flag = false;//同花标记位
	Type type = Kong;//同花类型
	int visited[14]{ 0 };
	int start = -1, end = -1;
	for (int i = 0; i < arr.size(); i++)
	{
		int value = arr[i] & 0x0f;
		if (flag == false)
		{
			switch (arr[i] & 0xf0)
			{
			case 0x00:type = Hei; break;
			case 0x10:type = Hong; break;
			case 0x20:type = Mei; break;
			case 0x30:type = Fang; break;
			default:
				return false;
			}
			flag = true;
		}
		if (flag && type != (arr[i] & 0xf0))
			return false;

		if (value == 1 || value == 2)
			return false;
		if (start == -1 && end == -1)
		{
			start = value;
			end = start;
		}
		else if (start > value)
			start = value;
		else if (end < value)
			end = value;
		if (visited[value] == 1)
			return false;
		visited[value] = 1;
	}
	if (start == end || end - start == (arr.size() - 1))
		return true;
	return false;
}

TIPS:使用判断顺子的第二种方式也可,可自行书写。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ufgnix0802

总结不易,谢谢大家的支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值