zoukankan      html  css  js  c++  java
  • 剑指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 <= 4;i++){
                if(nums[i] == 0) numberOfZero++;
            }
            for(int i = numberOfZero;i <= 3;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 <= 4;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)

  • 相关阅读:
    sql知识
    铁道部新客票系统设计(三)
    PYTHON压平嵌套列表
    快速升级App支持iOS6及iPhone5的4寸屏幕
    TreeListView
    杭州ADC技术嘉年华两日总结SOA,去C
    .NET(C#): Task.Unwrap扩展方法和async Lambda
    关于分布式系统的数据一致性问题
    wcf 随笔1
    Linux进程基础
  • 原文地址:https://www.cnblogs.com/Howfars/p/13390282.html
Copyright © 2011-2022 走看看