LeetCode 846 一手顺子
Alice 手中有一把牌,她想要重新排列这些牌,分成若干组,使每一组的牌数都是 groupSize
,并且由 groupSize
张连续的牌组成。
给你一个整数数组 hand
其中 hand[i]
是写在第 i
张牌,和一个整数 groupSize
。如果她可能重新排列这些牌,返回 true
;否则,返回 false
。
示例 1:
输入:hand = [1,2,3,6,2,3,4,7,8], groupSize = 3
输出:true
解释:Alice 手中的牌可以被重新排列为 [1,2,3],[2,3,4],[6,7,8]
。
示例 2:
输入:hand = [1,2,3,4,5], groupSize = 4 输出:false 解释:Alice 手中的牌无法被重新排列成几个大小为 4 的组。
提示:
1 <= hand.length <= 104
0 <= hand[i] <= 109
1 <= groupSize <= hand.length
贪心算法+哈希
- 利用哈希记录每个数字出现的次数
- 遍历数字,每个牌数是否存在长度为
groupSize
的连续牌数,如果牌数已经在长度为groupSize
的连续顺子中出现一次 ,就需要更新哈希表中该牌数出现的次数;继续统计该牌数剩余次数是否可以出现在新的连续顺子中,如果牌数的个数更新后为0,说明该牌数不会在新的顺子中出现,就需要从哈希表中移除掉; - 需要注意的是:数组按
groupSize
长度划分,说明数组长度须得是groupSize
的倍数,不然是无法划分的
/**
* 贪心算法
* @param hand
* @param groupSize
* @return
*/
public static boolean isNStraightHand(int[] hand, int groupSize) {
if (hand == null || hand.length == 0) return false;
int n = hand.length;
if (n % groupSize != 0) return false;
Arrays.sort(hand);
Map<Integer, Integer> integerMap = new TreeMap<>();
for (int x : hand) {
integerMap.put(x, integerMap.getOrDefault(x, 0) + 1);
}
// 遍历hand中元素
for (int x : hand) {
// 如果Map中不存在该值,判断下一个,有可能是当前值和前面的数字组成连续顺子
if (!integerMap.containsKey(x)) {
continue;
}
// 判断顺子,并更新数字出现的个数
for (int j = 0; j < groupSize; j++) {
int num = x + j;
// 如果不构成顺子,则直接返回false
if (!integerMap.containsKey(num)) {
return false;
}
integerMap.put(num, integerMap.get(num) - 1);
// 更新出现次数后为0,则移除该元素
if (0 == integerMap.get(num)) {
integerMap.remove(num);
}
}
}
return true;
}
测试用例
public static void main(String[] args) {
int[] hand = new int[]{1, 2, 3, 6, 2, 3, 4, 7, 8};
int groupSize = 3;
boolean flag = IsNStraightHand.isNStraightHand(hand, groupSize);
System.out.println("IsValidSudoku demo01 result : " + flag);
hand = new int[]{1, 2, 3, 4, 5};
groupSize = 4;
flag = IsNStraightHand.isNStraightHand(hand, groupSize);
System.out.println("IsValidSudoku demo02 result : " + flag);
}
测试结果
IsValidSudoku demo01 result : true
IsValidSudoku demo02 result : false