@Ggmatch
2018-02-11T02:47:21.000000Z
字数 3670
阅读 1382
剑指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;}
解决现实问题,很重要的一点就是要把问题可能出现的情况考虑周全,这道题的解题经过充分揭露了我考虑问题严密性的不足,也揭示了测试优先编程思想的重要性,每一种测试案例都代表一种情况的出现,把所有情况都考虑进来,这个程序的鲁棒性才会好,所以以后编程的时候在有了大致思路的时候,就要懂得自己寻找测试案例,然后边编程边修改程序。