扑克牌顺子判断
判断5张扑克牌是否为顺子,大小王可作为任意牌
问题
从扑克牌中随机抽取 5 张牌,判断是否为顺子(5 张牌连续)。其中 A 为 1,J 为 11,Q 为 12,K 为 13,大小王用 0 表示,可以替代任意数字。
示例:
[1, 2, 3, 4, 5]→true[0, 0, 1, 2, 5]→true(大小王补 3、4)[1, 2, 3, 4, 4]→false(有对子)
解答
思路
顺子的条件:
- 除 0 外没有重复的牌
- 最大值 - 最小值 < 5(0 不参与计算)
实现
/**
* 判断5张牌是否为顺子
* @param {number[]} nums - 5张牌,0表示大小王
* @return {boolean}
*/
function isStraight(nums) {
// 用 Set 检测重复
const set = new Set();
let max = 0;
let min = 14; // 牌最大是13
for (const num of nums) {
// 跳过大小王
if (num === 0) continue;
// 有重复牌,不可能是顺子
if (set.has(num)) return false;
set.add(num);
// 更新最大最小值
max = Math.max(max, num);
min = Math.min(min, num);
}
// 最大值和最小值差距小于5才能组成顺子
return max - min < 5;
}
测试
console.log(isStraight([1, 2, 3, 4, 5])); // true
console.log(isStraight([0, 0, 1, 2, 5])); // true
console.log(isStraight([0, 0, 2, 2, 5])); // false(有对子)
console.log(isStraight([11, 0, 9, 0, 8])); // true(8,9,10,11,12)
console.log(isStraight([1, 2, 12, 13, 0])); // false(差距太大)
排序解法
function isStraight(nums) {
// 排序
nums.sort((a, b) => a - b);
let jokers = 0; // 大小王数量
for (let i = 0; i < 4; i++) {
if (nums[i] === 0) {
jokers++;
continue;
}
// 有对子
if (nums[i] === nums[i + 1]) return false;
}
// 最大牌 - 最小非零牌 < 5
return nums[4] - nums[jokers] < 5;
}
关键点
- 顺子两个条件:无重复 + 极差小于 5
- 大小王(0)不参与重复检测和极差计算
- Set 解法时间复杂度 O(n),排序解法 O(n log n)
- 不需要真的去”填补”空缺,只需验证条件
目录