原题链接:扑克牌顺子_牛客题霸_牛客网
描述
现在有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(n) 的解法
输入描述:
输入五张扑克牌的值
返回值描述:
五张扑克牌能否组成顺子。
示例1
输入:
[6,0,2,0,4]
返回值:
true
说明:
中间的两个0一个看作3,一个看作5 。即:[6,3,2,5,4] 这样这五张牌在[2,6]区间连续,输出true
示例2
输入:
[0,3,2,6,4]
返回值:
true
示例3
输入:
[1,0,0,1,0] 返回值:
false
示例4
输入:
[13,12,11,0,1]
返回值:
false
解析思路:
这里既然说有O(n)复杂度的解法,那么我们自然要朝着O(n)的方向去解决。
说明数组只允许遍历一遍,则我们可以遍历一遍数组,找出最大最小值,以及记录每个值的数量,如果有重复则直接返回false。
然后从小往大查找,缺少则need0times加1。
比较完成后,分两种情况,
一种是最大最小值的差正好为4,则比较0的次数和need0times是否相等即可。
一种是最大最小值的差小于4,则比较0的次数是否大于这个差值即可。
PS:但是这种解题思路有个问题,时间复杂度O(n)没有问题,但是因为需要额外的空间去存储每个数值的数量,所以空间复杂度的话是O(n)了。这个目前没什么思路,看了网上的几种答案也都是有些问题的,这个如果有好的思路,欢迎讨论。
代码:
public boolean IsContinuous(int[] numbers) {
int max = -1;
int min = 14;
HashMap<Integer, Integer> timesMap = new HashMap<>();//HashMap其实可以用数组替换。但是这样空间复杂度就不是O(1)了
for (int i : numbers) {
Integer integer = timesMap.get(i);
if (integer == null) {
integer = 0;
}
timesMap.put(i, ++integer);
if (i < min && i != 0) {
min = i;
}
if (max < i) {
max = i;
}
}
if (min == 14 || max == -1) {
return false;
}
int need0times = 0;
int range = max - min;
if (range > 4) {
return false;
}
//2,5,0,0,0
for (int i = min; i <= max; i++) {
Integer integer = timesMap.get(i);
if (integer == null) {
need0times++;
continue;
}
if (need0times > 4) {
return false;
}
if (integer > 1) {
return false;
}
}
Integer num0Time = timesMap.get(0);//大小王的次数
if (num0Time == null) {
num0Time = 0;
}
if (range == 4 && num0Time == need0times) {
return true;
}
if (num0Time >= range) {
return true;
}
return false;
}