输入:
- 整数数组
hand表示手里的牌面值 - 整数
groupSize表示每组顺子的长度
要求:
- 把所有牌分成若干组
- 每组必须是
groupSize张连续牌 - 能分完返回
true,否则false
输出:
bool
思路:
这题的关键不是“怎么凑一组顺子”,而是:如果能成功分组,最小的牌一定只能作为某个顺子的起点(它不可能被更小的牌带着走,因为没有更小的了)。
所以策略很直接:
-
如果
hand.size() % groupSize != 0,直接不可能。 -
用
map<int,int> count统计每种牌出现次数(map自动按牌面升序)。 -
从
map.begin()开始扫每个牌startCard:
- 设
num = count[startCard],表示当前这个牌还剩多少张没被用掉。 - 如果
num > 0,说明我们必须以startCard作为起点,开num个顺子:- 需要把
[startCard, startCard+1, ..., startCard+groupSize-1]每个牌都扣掉num张 - 若其中某张牌数量不足(
count[currentCard] < num),直接失败
- 需要把
- 扫完不失败就成功。
这个贪心的本质是:先把最小牌“安置掉”,否则后面无论怎么分组它都会卡死。
复杂度:
- 时间复杂度:O(N log N)
- 建
map和后续访问都是log级
- 建
- 空间复杂度:O(N)(计数表)
class Solution {
public:
bool isNStraightHand(vector<int>& hand, int groupSize) {
if ((int)hand.size() % groupSize != 0) return false;
map<int, int> count;
for (int x : hand) {
count[x]++;
}
for (auto it = count.begin(); it != count.end(); ++it) {
int startCard = it->first;
int num = it->second;
if (num > 0) {
for (int i = 0; i < groupSize; ++i) {
int cur = startCard + i;
if (count[cur] < num) return false;
count[cur] -= num;
}
}
}
return true;
}
};
6591

被折叠的 条评论
为什么被折叠?



