剑指Offer 61、扑克牌中的顺子

274 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第9天,点击查看活动详情

题目:从若干副扑克牌中随机抽 5 张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A1J11Q12K13,而大、小王为 0 ,可以看成任意数字。A 不能视为 14

解题思路

解决本题首先需要理解顺子的含义,即连续的数字就构成顺子,在扑克牌中顺推,此处0,0,1,2,5可以组成顺子是因为这里的0,题目规定0可以当作任何数来用,所以当我们的数组不连续的时候,就可以使用0来替换,从而达到连续。例如0,0,1,2,5,此处包含两个0,我们可以将两个0分别看作是34,这样就构成了顺子。

本题最开始的思路是首先统计0的个数,之后对数组进行遍历,当遇到0直接跳过,每次查看后一个元素是否是前一个元素+1,但发现测试用例并不是有序的,因此首先需要对数组进行排序,但最终发现可能满足的条件无法一一列举,于是转换思路。

首先我们需要注意的是,在五张牌中除了大小王之外,不能出现重复的牌,若出现则不可能组成顺子,直接返回false即可。其次,我们需要统计五张牌中最大的牌和最小的,如果最大的牌和最小的牌之差大于等于5则必定不可能组成顺子,否则必然可以组成。

那根据上面两个条件,我们首先对数组进行排序,之后遍历数组,当元素为0的时候直接跳过,直到找到第一个元素不为0的位置,记录此位置,之后的循环中判断当前元素是否和前一个元素相等,相等则直接返回false,最终判断数组末尾元素减去记录位置的元素是否之差小于5即可。可得代码如下:

public boolean isStraight(int[] nums) {
    Arrays.sort(nums);
    int cur = 0;
    for(int i=0;i<nums.length;i++){
        if(nums[i]==0) {
            cur++;
            continue;
        }
        if(i>0&&nums[i] == nums[i-1]) return false;
    }
    return nums[nums.length-1] - nums[cur] < 5 ;
}