23 判断扑克牌的顺子

来源:互联网 发布:数控车床编程基础视频 编辑:程序博客网 时间:2024/05/16 07:34

前言

本博文部分图片, 思路来自于剑指offer 或者编程珠玑

问题描述

这里写图片描述

思路

对于这个问题, 书中给出了一种思路 [大小鬼使用数字0来表示]

思路一 : 先将数组进行排序, 然后获取到第一个非0元素的位置, 然后获取之后的元素的每两个相邻元素之间的差值[“空白元素部分”], 相邻两个元素相同为剪枝条件[根据题目的需求], 可以直接返回false, 统计所有的”空白元素”的个数, 最后比较总的”空白元素”的个数 和数组前面”0的个数”, 如果“空白元素”个数大于”0的个数”, 返回false[通配符都填充不满]


后面两种思路是我的
思路一 : 其实 和上面书中的思路基本上一致, 不过 我这里换了一种方式来统计, 使用的是标志数组

思路二 : 直接使用逻辑判定, 令”最大元素 和第一个非0元素的差值”为deltaVal, “最大元素的索引 和第一个非0元素的索引差值”为deltaIdx
    如果 delta大于了arr.length 表示就算吧所有的”0元素”都去补充空白, 仍然会存在空白, 返回false
    如果 deltaVal小于deltaIdx 表示”最大元素 和第一个非0元素”之间存在重复的数据, 返回false
    其他场景返回true

参考代码

/** * file name : Test19IsContinuousSeq.java * created at : 3:04:00 PM Jun 9, 2015 * created by 970655147 */package com.hx.test05;public class Test19IsContinuousSeq {    // 可以表示任意数字    static int ALL_MATCH = 0;    // 判断给定的序列是否是连续的   0可以表示任意数    public static void main(String []args) {        int[] arr = new int[] {3, 5, 4, 7 };        isContinuousSeq(arr);        isContinuousSeq02(arr);    }    // 思路 : 先将arr排序, 获取第一个非0的数字的索引        // 获取最大的数和第一个非0数之差, 获取最大数的索引和第一个非0数索引之差        // 先进行剪枝, 如果最大的差值大于了(索引差值+0的个数), 或者差值小于索引的差值, 则视为不可能连续, 直接返回false,     // 然后  利用一个长度为(deltaVal+1)的辅助数组  空间, 来记录那些数据存在    如果数组中空缺的数字个数大于了0的个数, 则视为, 即使使用了所有的0, 任然会存在空缺, 返回false        // 否则  返回true    public static void isContinuousSeq(int[] arr) {        Arrays.sort(arr);        int firstNonZeroIdx = getFirstNonAllMatchIdx(arr);        int deltaVal = arr[arr.length-1] - arr[firstNonZeroIdx];        int deltaIdx = arr.length-1 - firstNonZeroIdx;        // 数据的值相差太大的, 用0都不可能弥补的, 或者相差太小, 存在一个或多个一样的        if((deltaVal > deltaIdx + firstNonZeroIdx) || (deltaVal < deltaIdx) ) {            Log.log(false);            return ;        }        // 记录数据的存在情况        boolean[] isExists = new boolean[deltaVal + 1];        int falseNum = isExists.length;        boolean isContinuous = false;        for(int i=firstNonZeroIdx; i<arr.length; i++) {            if(arr[i] != ALL_MATCH) {                if(!isExists[arr[i] - arr[firstNonZeroIdx]]) {                    isExists[arr[i] - arr[firstNonZeroIdx]] = true;                    falseNum --;                }            }        }        isContinuous = falseNum <= firstNonZeroIdx;        Log.log(isContinuous);    }    // 在初始剪枝条件之后, 只需要判断是否存在重复的元素就好了    public static void isContinuousSeq02(int[] arr) {        Arrays.sort(arr);        int firstNonZeroIdx = getFirstNonAllMatchIdx(arr);        int deltaVal = arr[arr.length-1] - arr[firstNonZeroIdx];        int deltaIdx = arr.length-1 - firstNonZeroIdx;        // 数据的值相差太大的, 用0都不可能弥补的, 或者相差太小, 存在一个或多个一样的        if((deltaVal > deltaIdx + firstNonZeroIdx) || (deltaVal < deltaIdx) ) {            Log.log(false);            return ;        }        Log.log(true);    }    // 获取arr中第一个非0 的数据的索引    private static int getFirstNonAllMatchIdx(int[] arr) {        int idx = -1;        for(int i=0; i<arr.length; i++) {            if(arr[i] != ALL_MATCH) {                idx = i;                break ;            }        }        return idx;    }}

效果截图

这里写图片描述

总结

对于排序的操作, 因为差值范围不大, 可以采用O(n)的桶排序
查找非0元素的操作, 因为是有序嘛, 可以采用二分查找的思路针对当前场景进行改写

注 : 因为作者的水平有限,必然可能出现一些bug, 所以请大家指出!

0 0
原创粉丝点击