通过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:使用判断顺子的第二种方式也可,可自行书写。