题目描述:
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh,My God!”不是顺子…LL不高兴了,他想了想,决定大\小王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何,如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
思路分析:
开始时候的思路,先排序数组,然后统计0的个数,然后再按照0出现的次数分别处理数组。本题的主要时间复杂度在于排序数组上。
原始代码实现如下:
//初步想法,根据0的个数来判断数组
//先排序,然后统计0的个数
//还得考虑重复的情况
//总和一下,判断的条件就是数组的相邻两个数的间隔之和不能大于4
import java.util.Arrays;
public class Solution {
public boolean isContinuous(int [] numbers) {
if(numbers == null || numbers.length < 5 ){
return false;
}
//先排序
boolean flag = true;
Arrays.sort(numbers);
int numzero = 0;//记录0的个数
int sum = 0 ; //记录间隔的和
int length = numbers.length;
for(int i = 0 ; i < length ; i++){
if(numbers[i] == 0){
numzero++;
}
if(numbers[i]>0){//排序后的数组,大于0后面肯定不会再次出现0了。
break;
}
}
//0的个数最多为四个,所以当抽到四个0的时候,肯定是没有问题的
//当没0的时候就需要判断数组是否是连续的了
if( numzero == 0){
//遍历数组,判断是否连续
for(int i = 1 ; i < length ; i++){
//当相邻两个数间隔大于1的时候,判定为false;
if(numbers[i]-numbers[i-1]>1){
flag = false;
break;
}
if(numbers[i] == numbers[i-1]){//去重
return false;
}
}
}else if(numzero == 1){
//当数组中只有一个0的时候,数组中相邻两个数间隔之和不能大于4
for(int i = 2 ; i < length ; i++){
sum+=numbers[i]-numbers[i-1];
if(numbers[i] == numbers[i-1]){
return false;
}
}
if(sum > 4){
flag = false;
}
}else if(numzero == 2){
//当数组中有两个0的时候,这时候需要判断余下的三个数的间隔之和不能大于4
for(int i = 3 ; i < length ; i++){
sum+=numbers[i]-numbers[i-1];
if(numbers[i] == numbers[i-1]){//去重
return false;
}
}
if(sum > 4){
flag = false;
}
}else if(numzero == 3){
//当存在三个0的时候,剩余的两个数的差值不能大于4
for(int i = 4 ; i < length ; i++){
sum+=numbers[i]-numbers[i-1];
if(numbers[i] == numbers[i-1]){//去重
return false;
}
}
if(sum > 4){
flag = false;
}
}else{
//存在四个0的时候,肯定能组成连续数字
flag = true;
}
return flag;
}
}
改进一:
然后发现每次判断0的时候,for循环的起始位置不就是0的个数+1么,那我为什么还要分别判断,直接缩写成一个表达式不就行了,开始的时候简直愚蠢。改进的代码实现如下:
import java.util.Arrays;
public class Solution {
public boolean isContinuous(int [] numbers) {
if(numbers == null || numbers.length < 5 ){
return false;
}
//先排序
boolean flag = true;
Arrays.sort(numbers);
int numzero = 0;//记录0的个数
int sum = 0 ; //记录间隔的和
int length = numbers.length;
for(int i = 0 ; i < length ; i++){
if(numbers[i] == 0){
numzero++;
}
if(numbers[i]>0){//排序后的数组,大于0后面肯定不会再次出现0了。
break;
}
}
//记录非0的间隔类和
for(int i = numzero+1 ; i < length ; i++){
sum+=numbers[i]-numbers[i-1];
if(numbers[i] == numbers[i-1]){
return false;
}
}
if(sum > 4){
flag = false;
}
return flag;
}
}
改进二:
这时候又想到,间隔累和不就是最大值和最小值之间的差值么,那我为什么还要累加,这不是脱裤子放屁多此一举么,又犯傻了!!!改进的代码实现如下:
import java.util.Arrays;
public class Solution {
public boolean isContinuous(int [] numbers) {
//先判空
if(numbers == null || numbers.length < 5 ){
return false;
}
//先排序
boolean flag = true;
Arrays.sort(numbers);
int numzero = 0;//记录0的个数
int interval = 0 ; //记录最大值和最小值的差值
int length = numbers.length;
for(int i = 0 ; i < length ; i++){
if(numbers[i] == 0){
numzero++;
}
if(numbers[i]>0){//排序后的数组,大于0后面肯定不会再次出现0了。
break;
}
}
//遍历数组的非零元素,判断是否有重复的数字。
for(int i = numzero+1 ; i < length ; i++){
if(numbers[i] == numbers[i-1]){
return false;
}
}
//非零数值,最大最小值不能超过4,否则一定不可能组成顺子
interval = numbers[length-1]-numbers[numzero];
if( interval > 4){
flag = false;
}
return flag;
}
}
经过一系列的改进,代码最终变得稍微简洁明了,开始写的时候有点犯傻,疯狂写if else。简直愚蠢!!!还得再接再厉!!!以上只是本人的思维总结,不足之处希望大家批评指正。