剑指Offer_#61_扑克牌中的顺子

剑指Offer_#61_扑克牌中的顺子

Contents

题目

从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14。

示例 1:
输入: [1,2,3,4,5]
输出: True
示例 2:
输入: [0,0,1,2,5]
输出: True

限制:
数组长度为 5 
数组的数取值为 [0, 13] .

思路分析

顺子的判断方法

一个连续的数组是否是顺子,需要满足两个条件。
条件1:没有重复牌
除了0之外,5个数字当中没有对子,即没有相同的两个牌。
条件2:0可以补齐缺失的牌

  1. 0的个数 ≥ 间隔的个数。间隔指的是连续数字中缺失的那些数字,这些数字可以由0来补齐。
  2. max - min <= 4
    • 如果最大值和最小值差距大于4,那么连续数组的长度一定大于5,但是输入数组只有5个数字,那么必定存在漏掉的数字,不可能是连续的。
    • 对于连续的5个数字,最大值和最小值之间刚好相差4。最大值和最小值差距小于4时,[min...max]之间的数字个数少于5个,min和max之外剩下的数字只有可能是0或者minmax之间的数,一定可以构成一个连续数组。

方法1:比较0的个数与间隔个数

  1. 排序,0必然出现在最前面
  2. 遍历数组,统计间隔的数量及0的数量
    • 遍历过程中发现相同的数,直接返回false
  3. 比较0的个数和间隔的个数,0的个数如果大于等于间隔的个数,返回true,否则返回false

方法2:HashSet方法

  • max - min <= 4,如果是5张连续牌,最大与最小牌的差距最多到4。即需要统计最大牌和最小牌,通过循环遍历实现。这个方法避免了统计缺失的数字,还有0的个数。
  • 出现对子,直接返回false。所以需要判别重复。想到用Set数据结构,可以最快的找出重复,避免了排序。
    • Set<Integer> set = new HashSet<>();

解答

解答1:比较0的个数和间隔的个数

class Solution {
    public boolean isStraight(int[] nums) {
        //1.排序,0必然出现在最前面
        Arrays.sort(nums);
        int numberOfZero = 0;
        int numberOfGap = 0;
        //2.遍历数组,统计间隔的数量及0的数量
        for(int i = 0;i <= nums.length - 1;i++){
            if(nums[i] == 0) numberOfZero++;
        }
        for(int i = numberOfZero;i <= nums.length - 2;i++){
            //出现一对相同数,不可能是顺子
            if(nums[i] == nums[i + 1]) return false;
            numberOfGap += nums[i+1] - nums[i] - 1;
        }
        return numberOfZero >= numberOfGap;
    }
}

复杂度分析

时间复杂度:O(nlogn),排序的复杂度是O(nlogn)
空间复杂度:O(1)

解答2:利用HashSet判断重复

class Solution {
    public boolean isStraight(int[] nums) {
        Set<Integer> set = new HashSet<>();
        //注意max和min的初始化,max要初始化为比最小值1还小的0,min要初始化为比最大的13还大的14
        //目的是:进入循环后,一开始就会更新
        int max = 0;
        int min = 14;
        for(int i = 0;i <= nums.length - 1;i++){
            //0不统计在内
            if(nums[i] == 0) continue;
            //更新最大值和最小值
            max = Math.max(max, nums[i]);
            min = Math.min(min, nums[i]);
            if(set.contains(nums[i])) return false;
            set.add(nums[i]);
        }
        return max - min <= 4;
    }
}

复杂度分析

时间复杂度:O(n)
空间复杂度:O(n)

posted @ 2020-07-28 11:49  Howfar's  阅读(176)  评论(0编辑  收藏  举报