第六十一题:扑克牌中的顺子
题目:从扑克牌中随机抽取 5 张牌,判断是不是一个顺子,即这张牌是不是连续的。2 ~ 10 为数字本身, A 为 1,J 为 11,Q 为 12,K 为 13,而大、小王也可以看成任意数字。
解题程序:
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<list>
using namespace std;
int compare(const void *arg1,const void *arg2)
{
return *(int*)arg1 - *(int*)arg2;
}
bool isContinuous(int *numbers,int length)
{
if( numbers == NULL || length <1 )
return false;
// 先把数组排序
qsort(numbers,length,sizeof(int),compare);
int numberOfZero = 0;
int numberOfGap = 0;
// 统计数组中 0 的个数
for(int i =0;i<length && numbers[i] == 0;i++)
numberOfZero++;
// 统计数组中空缺总数
int small = numberOfZero;
int big = small+1;
// 统计排序后的相邻数字之间的空缺总数
while(big<length)
{
// 两个数字不相等,有对子,不可能是顺序
if(numbers[small] == numbers[big])
return false;
numberOfGap += numbers[big] - numbers[small] - 1;
small = big;
big++;
}
return (numberOfGap>numberOfZero) ? false : true;
}
// 测试用例:
void test()
{
int num1[] = {1,3,2,5,4};
if(isContinuous(num1,5))
printf("num1 中的五张扑克牌是连续的!\n");
else
printf("num1 中的五张扑克牌是不连续的!\n");
int num2[] = {1,3,2,6,4};
if(isContinuous(num2,5))
printf("num2 中的五张扑克牌是连续的!\n");
else
printf("numk 中的五张扑克牌是不连续的!\n");
int num3[] = {0,3,2,6,4};
if(isContinuous(num3,5))
printf("num2 中的五张扑克牌是连续的!\n");
else
printf("num3 中的五张扑克牌是不连续的!\n");
int num4[] = {0,3,1,6,4};
if(isContinuous(num4,5))
printf("num4 中的五张扑克牌是连续的!\n");
else
printf("num4 中的五张扑克牌是不连续的!\n");
int num5[] = {1,3,0,5,0};
if(isContinuous(num5,5))
printf("num5 中的五张扑克牌是连续的!\n");
else
printf("num5 中的五张扑克牌是不连续的!\n");
int num6[] = {1,3,0,7,0};
if(isContinuous(num6,5))
printf("num6 中的五张扑克牌是连续的!\n");
else
printf("num6 中的五张扑克牌是不连续的!\n");
}
int main(void)
{
test();
return 0;
}
第六十二题:圆圈中最后剩下的数字
题目:0,1,2,3,4,....... ,n - 1 这 n 个数字排成一个圆圈,从数字 0 开始,每次从这个圆圈里删除第 m 个数字。求出这个圈里剩下的最后一个数字。
解题程序:
include<iostream>
#include<stdio.h>
#include<list>
using namespace std;
// 经典解法,用环形链表模拟
int LastRemaining(unsigned int n,unsigned int m)
{
if(n<1||m<1)
return -1;
unsigned int i = 0;
list<int> numbers;
for(i=0;i<n;i++)
numbers.push_back(i);
list<int>::iterator current = numbers.begin();
while(numbers.size()>1)
{
for( i =1;i<m;i++ )
{
current++;
if( current == numbers.end() )
current = numbers.begin();
}
list<int>::iterator next = ++current;
if(next == numbers.end())
next = numbers.begin();
--current;
numbers.erase(current);
current = next;
}
return *current;
}
// 创新的解法
int LastRemaining1(int n,int m)
{
if(n<1||m<1)
return -1;
int last = 0;
for(int i =2;i<=n;i++)
last = (last+m) % i;
return last;
}
// 测试用例:
void test()
{
int n,m;
printf("请输入数字 n 和 m :\n");
scanf("%d%d",&n,&m);
printf("解法一:\n");
int ret = LastRemaining(n,m);
if( ret == -1 )
printf("输入有误!\n");
else
printf("最后一个数字是:%d\n",ret);
printf("解法二:\n");
ret = LastRemaining1(n,m);
if( ret == -1 )
printf("输入有误!\n");
else
printf("最后一个数字是:%d\n",ret);
}
int main(void)
{
test();
return 0;
}