【剑指offer】62.扑克牌顺子
总目录:
1.问题描述
现在有2副扑克牌,从扑克牌中随机五张扑克牌,我们需要来判断一下是不是顺子。
有如下规则:
1. A为1,J为11,Q为12,K为13,A不能视为14
2. 大、小王为 0,0可以看作任意牌
3. 如果给出的五张牌能组成顺子(即这五张牌是连续的)就输出true,否则就输出false。
4.数据保证每组5个数字,每组最多含有4个零,数组的数取值为 [0, 13]
有如下规则:
1. A为1,J为11,Q为12,K为13,A不能视为14
2. 大、小王为 0,0可以看作任意牌
3. 如果给出的五张牌能组成顺子(即这五张牌是连续的)就输出true,否则就输出false。
4.数据保证每组5个数字,每组最多含有4个零,数组的数取值为 [0, 13]
要求:空间复杂度 O(1),时间复杂度 O(nlogn),本题也有时间复杂度 O(n)的解法
2.问题分析
前提条件:除0外,不允许有重复数字
1排序+遍历
先排序,然后统计0的数量,再统计空缺的数量,最后检查0的数量是否能弥补空缺的数量(空缺:两个相邻数字之间的间隔)
2最大最小值+现成的集合查重
用现成的集合来保存数据方便查重
最大值-最小值<5
3最大最小值+二进制查重
一共只有5个数字,使用二进制bit标志位来表示[1~13]之间的数字是否出现过
flag&(1<<val)!=0表示val已经重复
flag|=(1<<val)表示val出现过
3.代码实例
排序+遍历
1 class Solution { 2 public: 3 int minVal = 1, maxVal = 13; 4 bool IsContinuous( vector<int> numbers ) { 5 //数据量 6 int dataSize = numbers.size(); 7 if (dataSize != 5) { 8 return false; 9 } 10 11 int zero_num = 0;//0的个数 12 int interrupt = 0;//记录五张牌中最大值max到最小值min的距离 13 sort(numbers.begin(), numbers.end()); 14 15 int i = 0; 16 while (numbers[i] == 0)zero_num++,i++;//统计0的个数 17 for (; i < numbers.size()-1; ++i) { 18 if (numbers[i] == numbers[i + 1])return false;//出现相同的扑克牌 19 interrupt += numbers[i + 1] - numbers[i] - 1;//计算距离 20 } 21 22 //如果可以弥补空缺 23 if (zero_num >= interrupt) return true; 24 return false; 25 } 26 };
最大最小值+现成的集合查重
1 class Solution { 2 public: 3 bool IsContinuous( vector<int> numbers ) { 4 //数据量 5 int dataSize = numbers.size(); 6 if (dataSize != 5) { 7 return false; 8 } 9 10 int curMax = 1, curMin = 14; 11 set<int> curSet; 12 for (int i : numbers) { 13 //跳过0 14 if (i == 0) continue; 15 16 //更新最大最小值 17 curMax = max(i, curMax); 18 curMin = min(i, curMin); 19 20 //存在重复值 21 if (curSet.count(i)) return false; 22 23 //记录 24 curSet.insert(i); 25 } 26 27 return (curMax - curMin) < 5; 28 } 29 };
最大最小值+二进制标记位
1 class Solution { 2 public: 3 bool IsContinuous( vector<int> numbers ) { 4 //数据量 5 int dataSize = numbers.size(); 6 if (dataSize != 5) { 7 return false; 8 } 9 10 int curMax = 1, curMin = 14; 11 int flag = 0; 12 for (int i : numbers) { 13 //跳过0 14 if (i == 0) continue; 15 16 //更新最大最小值 17 curMax = max(i, curMax); 18 curMin = min(i, curMin); 19 20 //存在重复值 21 if ((flag & (1 << i)) != 0) return false; 22 flag |= (1 << i); 23 } 24 25 return (curMax - curMin) < 5; 26 } 27 };