【剑指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]
要求:空间复杂度 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 };

 

posted @ 2022-12-03 17:28  啊原来是这样呀  阅读(121)  评论(0编辑  收藏  举报