@Ggmatch
2018-02-11T10:47:21.000000Z
字数 3670
阅读 1266
剑指offer
c++
算法
从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任何数字(这里看成0)。
1.第一个版本:少了异常情况的处理
#include "stdafx.h"
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
bool comp(int, int);
/*
目的:判断当前序列的5个元素能够构成一个顺子
思路:1. 5张牌全在1-13中。排序,判断是否连续
2. 5张牌部分在1-13中,有大小王。排序后,计算出断掉的元素个数,若==大小王个数,则连续;否则,不连续
*/
bool IsContinuous(vector<int> numbers)
{
// 1.排序
sort(numbers.begin(),numbers.end(), comp);
// 2.计算出0的个数
vector<int>::iterator iter = numbers.begin();
int numbersOf0 = 0;
for (;(*iter) == 0 && iter != numbers.end();++iter)
{
numbersOf0++;
}
// 3.计算出断掉的元素个数
int uncontinuousElements = 0;
int big,small;
big = small = *iter;
while (++iter != numbers.end())
{
big = *iter;
if (big != small + 1)
uncontinuousElements+=big-small-1;
small = big;
}
// 4.判断两者大小关系
if (numbersOf0 == uncontinuousElements)
return false;
return true;
}
bool comp(int param1, int param2)
{
// 升序
return param1<param2;
}
2.第二个版本:少了大小王个数>间隔元素的个数
#include "stdafx.h"
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
bool comp(int, int);
/*
目的:判断当前序列的5个元素能够构成一个顺子
思路:1. 5张牌全在1-13中。排序,判断是否连续
2. 5张牌部分在1-13中,有大小王。排序后,计算出断掉的元素个数,若==大小王个数,则连续;否则,不连续
*/
bool IsContinuous(vector<int> numbers)
{
// 0.处理异常情况
if (numbers.size() < 5)
return false;
// 1.排序
sort(numbers.begin(),numbers.end(), comp);
// 2.计算出0的个数
vector<int>::iterator iter = numbers.begin();
int numbersOf0 = 0;
for (;(*iter) == 0 && iter != numbers.end();++iter)
{
numbersOf0++;
}
// 3.计算出断掉的元素个数
int uncontinuousElements = 0;
int big,small;
big = small = *iter;
while (++iter != numbers.end())
{
big = *iter;
if (big != small + 1)
uncontinuousElements+=big-small-1;
small = big;
}
// 4.判断两者大小关系
if (numbersOf0 == uncontinuousElements)
return false;
return true;
}
3.第三个版本:少了对子的情况
#include "stdafx.h"
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
bool comp(int, int);
/*
目的:判断当前序列的5个元素能够构成一个顺子
思路:1. 5张牌全在1-13中。排序,判断是否连续
2. 5张牌部分在1-13中,有大小王。排序后,计算出断掉的元素个数,若<=大小王个数,则连续;否则,不连续
*/
bool IsContinuous(vector<int> numbers)
{
// 0.处理异常情况
if (numbers.size() < 5)
return false;
// 1.排序
sort(numbers.begin(),numbers.end(), comp);
// 2.计算出0的个数
vector<int>::iterator iter = numbers.begin();
int numbersOf0 = 0;
for (;(*iter) == 0 && iter != numbers.end();++iter)
{
numbersOf0++;
}
// 3.计算出断掉的元素个数
int uncontinuousElements = 0;
int big,small;
big = small = *iter;
while (++iter != numbers.end())
{
big = *iter;
if (big != small + 1)
uncontinuousElements+=big-small-1;
small = big;
}
// 4.判断两者大小关系
if (numbersOf0 < uncontinuousElements)
return false;
return true;
}
4.最终版本
#include "stdafx.h"
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
bool comp(int, int);
/*
目的:判断当前序列的5个元素能够构成一个顺子
思路:1. 5张牌全在1-13中。排序,判断是否连续
2. 5张牌部分在1-13中,有大小王。排序后,计算出断掉的元素个数,若<=大小王个数,则连续;否则,不连续
*/
bool IsContinuous(vector<int> numbers)
{
// 0.处理异常情况
if (numbers.size() < 5)
return false;
// 1.排序
sort(numbers.begin(),numbers.end(), comp);
// 2.计算出0的个数
vector<int>::iterator iter = numbers.begin();
int numbersOf0 = 0;
for (;(*iter) == 0 && iter != numbers.end();++iter)
{
numbersOf0++;
}
// 3.计算出断掉的元素个数
int uncontinuousElements = 0;
int big,small;
big = small = *iter;
while (++iter != numbers.end())
{
big = *iter;
// 处理对子的情况
if (big == small)
return false;
if (big != small + 1)
uncontinuousElements+=big-small-1;
small = big;
}
// 4.判断两者大小关系
if (numbersOf0 < uncontinuousElements)
return false;
return true;
}
bool comp(int param1, int param2)
{
// 升序
return param1<param2;
}
int main()
{
// 测试
vector<int> vec1 = { 3,2,5,6,7 };
vector<int> vec2 = { 3,0,5,6,7 };
vector<int> vec3 = {2,5,6,7};
vector<int> vec4 = { 4,0,0,0,0 };
vector<int> vec5 = { 1,1,0,0,0 };
// 无大小王
bool result1 = IsContinuous(vec1);
// 有大小王
bool result2 = IsContinuous(vec2);
bool result4 = IsContinuous(vec4);
// 不足5个元素
bool result3 = IsContinuous(vec3);
// 出现对子
bool result5 = IsContinuous(vec5);
// 打印结果
printf("%d %d %d %d %d\n", result1, result2, result3,result4,result5);
return 0;
}
解决现实问题,很重要的一点就是要把问题可能出现的情况考虑周全,这道题的解题经过充分揭露了我考虑问题严密性的不足,也揭示了测试优先编程思想的重要性,每一种测试案例都代表一种情况的出现,把所有情况都考虑进来,这个程序的鲁棒性才会好,所以以后编程的时候在有了大致思路的时候,就要懂得自己寻找测试案例,然后边编程边修改程序。