面试题61. 扑克牌中的顺子
题目:
思路:
【1】由于题目没有说明输入是无序的还是有序的,默认是无序,然而在无序中,如【4,7,5,9,2】我们比较难准确的知道是否需要鬼来填充。所以考虑将数组先进行排序。排完序之后就好处理很多了,针对顺序数组,我们知道如果出现重复的数字必然不可能成为顺子。那么其他的就要看间隔的数字与鬼牌的数量是否对应的上。
【2】同理,衍生除了另外的思路,如记录最大值和最小值,只要相差不大于4,那么其余的就可以组成顺子(注意这里也是要考虑如果出现重复的数字也是不可能成为顺子的,所以也是需要排序或者使用辅助空间来鉴别)
代码展示:
根据最大和最小值的差额来判断的思路:
//时间0 ms击败100% //内存39.4 MB击败14.10% //首先是基于数组的数据是无序的 class Solution { public boolean isStraight(int[] nums) { int poker = 0,min = 14,max = 0; Arrays.sort(nums); for (int x : nums){ if (x == 0) continue; //出现重复的牌必然不能成为顺子 if (poker == x) return false; poker = x; max = Math.max(max,x); min = Math.min(min,x); } return max - min < 5; } } //时间0 ms击败100% //内存39 MB击败59.97% class Solution { public boolean isStraight(int[] nums) { Set<Integer> repeat = new HashSet<>(); int max = 0, min = 14; for(int num : nums) { if(num == 0) continue; // 跳过大小王 max = Math.max(max, num); // 最大牌 min = Math.min(min, num); // 最小牌 if(repeat.contains(num)) return false; // 若有重复,提前返回 false repeat.add(num); // 添加此牌至 Set } return max - min < 5; // 最大牌 - 最小牌 < 5 则可构成顺子 } }
根据需要鬼牌的数量和真实鬼牌的对比的方式判断:
//时间0 ms击败100% //内存39.4 MB击败12.38% class Solution { public boolean isStraight(int[] nums) { Arrays.sort(nums); int joker = 0; int need = 0; for(int i = 0;i<nums.length-1;i++){ if(nums[i]==0){ joker++; continue; } if(nums[i+1]==nums[i]){ return false; } if(nums[i+1]-nums[i]>=1){ need = need+(nums[i+1]-nums[i]-1); } } return need<=joker; } }