LeetCode 剑指 Offer 61. 扑克牌中的顺子
题目描述

思路分析
解法一:哈希集合(推荐)
核心思路:
- 大小王(数字 0)可代替任意牌,因此先统计 0 的个数,再判断非零牌。
- 顺子的两个充分必要条件:① 非零牌中没有重复;② 非零牌的最大值与最小值之差小于 5。
- 使用哈希集合在遍历过程中同时完成去重检查和 max/min 的维护,一次遍历即可得出结论。
复杂度分析:
- 时间复杂度:O(n),其中 n 表示数组长度(固定为 5),遍历一次数组。
- 空间复杂度:O(n),哈希集合最多存储 n 个元素。
class Solution {
public boolean isStraight(int[] nums) {
Set<Integer> set = new HashSet<>();
int max = 0, min = 14;
for (int num : nums) {
// 跳过大小王
if (num == 0) {
continue;
}
// 非零牌有重复,直接返回 false
if (!set.add(num)) {
return false;
}
max = Math.max(max, num);
min = Math.min(min, num);
}
// 最大值与最小值之差小于 5,即可构成顺子
return max - min < 5;
}
}
func isStraight(nums []int) bool {
set := make(map[int]bool)
max, min := 0, 14
for _, num := range nums {
// 跳过大小王
if num == 0 {
continue
}
// 非零牌有重复,直接返回 false
if set[num] {
return false
}
set[num] = true
if num > max {
max = num
}
if num < min {
min = num
}
}
// 最大值与最小值之差小于 5,即可构成顺子
return max-min < 5
}
解法二:排序 + 遍历
核心思路:
- 对数组排序后,所有 0(大小王)会集中在数组头部。
- 统计 0 的个数(即”万能牌”数量),然后从第一张非零牌开始检查相邻两牌之差。
- 若相邻牌相等(有重复),直接返回 false;否则累计差值缺口,最终判断缺口是否能被 0 填满。
- 等价地:排序后只需检查
nums[4] - nums[jokers] < 5(jokers 为 0 的个数)。
复杂度分析:
- 时间复杂度:O(n log n),其中 n 表示数组长度(固定为 5),排序开销。
- 空间复杂度:O(1),仅使用常数级额外空间。
class Solution {
public boolean isStraight(int[] nums) {
Arrays.sort(nums);
int jokers = 0;
for (int 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;
}
}
func isStraight(nums []int) bool {
sort.Ints(nums)
jokers := 0
for 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
}
相似题目
| 题目 | 难度 | 考察点 |
|---|---|---|
| 268. 丢失的数字 | 简单 | 数学 / 哈希表 |
| 剑指 Offer 03. 数组中重复的数字 | 简单 | 哈希表 / 原地交换 |
| 442. 数组中重复的数据 | 中等 | 原地哈希 |
| 645. 错误的集合 | 简单 | 哈希表 / 数组标记 |
| 128. 最长连续序列 | 中等 | 哈希集合 |
| 41. 缺失的第一个正数 | 困难 | 原地哈希 |
本博客所有文章除特别声明外,均采用
CC BY-NC-SA 4.0
许可协议,转载请注明出处!