更多剑指offer面试习题请点击:《剑指offer》(第二版)题集目录索引
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。
这里我们可以把五张牌看作一个数组,数组里面有五个数字(大小王均看作0)。接下来要做的事就是判断这五个数字是否连续。
首先我们把这个数组进行排序,这里我是自己写了一个直插排序。然后因为0比较特殊(可以看作任何数字),我们用一个for循环统计出数组中0(即大小王)出现的次数times_of_zero
。接下来我们就可以遍历数组判断数组元素是否连续。
遍历数组时要记得从第一个非0元素开始。判断后一个数和前一个数数值之差gab
。
1. 如果gab == 0
,那表示这两个数相等(是顺子),直接返回false;
2. 如果gab == 1
,属于正常现象,表示这两个数是连续的(两张牌是连续的);
3. 如果gab > 1
,表示这两张牌之间差了gab-1
张牌。因为0可以变成任意数,那就可以用gab-1
个0来填补中间的空缺,使之连续。
循环过程中,如果出现times_of_zero < 0
的情况,那表示这五张牌中空缺太多了,没那么多0让你来补(一副牌就2两个大小王),那么就可以判断这副牌不是顺子;如果循环结束后times_of_zero >= 0
这说明五张牌肯定能组成顺子,返回true。
// 直插排序
void Insert(int* numbers, int length)
{
if (nullptr == numbers || length <= 1)
return;
int i = 0;
int end = 0;
for (; i < length - 1; ++i)
{
end = i;
while (end >= 0)
{
if (numbers[end] > numbers[end + 1])
{
int tmp = numbers[end];
numbers[end] = numbers[end + 1];
numbers[end + 1] = tmp;
}
--end;
}
}
}
// 判断是否为顺子
bool IsContinuous(int* numbers, int length)
{
// 输入的数组不合法
if (nullptr == numbers || length <= 0)
return false;
// 对数组进行排序
Insert(numbers, length);
// 记录数组中0的个数(牌中大小王的个数)
int times_of_zero = 0;
// 记录相邻两个元素的值差
int gap = 0;
// 统计0的个数
int i = 0;
for (; i < length; ++i)
{
if (0 == numbers[i])
++times_of_zero;
}
// 从非0位置开始计算
i = times_of_zero;
while (i < length - 1 && times_of_zero >= 0)
{
gap = numbers[i + 1] - numbers[i];
// 两个数相等(对子)
if (0 == gap)
{
return false;
}
// 两张牌不连续,用大小王来填充
else
{
times_of_zero -= (gap - 1);
}
++i;
}
return times_of_zero < 0 ? false : true;
}
void Test(const char* testName, int* numbers, int length, bool expected)
{
if (testName != nullptr)
printf("-6%s begins: ", testName);
if (IsContinuous(numbers, length) == expected)
printf("Passed.\n");
else
printf("Failed.\n");
}
void Test1()
{
int numbers[] = { 1, 3, 2, 5, 4 };
Test("Test1", numbers, sizeof(numbers) / sizeof(int), true);
}
void Test2()
{
int numbers[] = { 1, 3, 2, 6, 4 };
Test("Test2", numbers, sizeof(numbers) / sizeof(int), false);
}
void Test3()
{
int numbers[] = { 0, 3, 2, 6, 4 };
Test("Test3", numbers, sizeof(numbers) / sizeof(int), true);
}
void Test4()
{
int numbers[] = { 0, 3, 1, 6, 4 };
Test("Test4", numbers, sizeof(numbers) / sizeof(int), false);
}
void Test5()
{
int numbers[] = { 1, 3, 0, 5, 0 };
Test("Test5", numbers, sizeof(numbers) / sizeof(int), true);
}
void Test6()
{
int numbers[] = { 1, 3, 0, 7, 0 };
Test("Test6", numbers, sizeof(numbers) / sizeof(int), false);
}
void Test7()
{
int numbers[] = { 1, 0, 0, 5, 0 };
Test("Test7", numbers, sizeof(numbers) / sizeof(int), true);
}
void Test8()
{
int numbers[] = { 1, 0, 0, 7, 0 };
Test("Test8", numbers, sizeof(numbers) / sizeof(int), false);
}
void Test9()
{
int numbers[] = { 3, 0, 0, 0, 0 };
Test("Test9", numbers, sizeof(numbers) / sizeof(int), true);
}
void Test10()
{
int numbers[] = { 0, 0, 0, 0, 0 };
Test("Test10", numbers, sizeof(numbers) / sizeof(int), true);
}
// 有对子
void Test11()
{
int numbers[] = { 1, 0, 0, 1, 0 };
Test("Test11", numbers, sizeof(numbers) / sizeof(int), false);
}
// 鲁棒性测试
void Test12()
{
Test("Test12", nullptr, 0, false);
}
int main()
{
Test1();
Test2();
Test3();
Test4();
Test5();
Test6();
Test7();
Test8();
Test9();
Test10();
Test11();
Test12();
system("pause");
return 0;
}