面试题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;
    }
}

 

posted @ 2023-02-15 14:19  忧愁的chafry  阅读(36)  评论(0编辑  收藏  举报