Hand of Straights
Medium · Greedy · Explanation and code example
Hash Map
How it works
We need to split the hand into groups of size groupSize, where each group is made of consecutive numbers and every card is used exactly once.
This approach uses only a frequency map and a simple rule:
- Any valid group must start at the beginning of a consecutive run
- So for a given number
num, we first walk left to find the earliest possible start of its run (we keep moving left whilestart - 1still exists in the hand) - Once we know a possible start, we try to repeatedly form consecutive groups starting from that start:
- while there are still cards at
start, we build a group:start,start+1, ...,start+groupSize-1 - decrement counts as we use cards
- while there are still cards at
By always forming groups from the earliest start in a run, we avoid skipping needed smaller cards and ensure groups remain consecutive.
Steps
- If
len(hand)is not divisible bygroupSize, returnfalse. - Build a frequency map
countfor all card values. - For each card value
numin the hand:- Find the earliest start of the consecutive run containing
num:- set
start = num - while
count[start - 1] > 0, decrementstart
- set
- Find the earliest start of the consecutive run containing
- For every possible
startup tonum:- While
count[start] > 0:- Try to create one full group starting at
start - For each
ifromstarttostart + groupSize - 1:- If
count[i] == 0, returnfalse(missing a needed card) - Otherwise decrement
count[i]
- If
- Try to create one full group starting at
- Move
startforward by1and continue
- While
- If all groups are formed successfully, return
true.
Complexity
- Time complexity:
O(n) - Space complexity:
O(n)
Things to watch for
Forgetting to Check Divisibility First
If the total number of cards is not divisible by groupSize, it is impossible to form complete groups. Skipping this initial check wastes time processing the array and may lead to subtle bugs where the algorithm appears to succeed but produces an invalid grouping.
Not Starting Groups from the Smallest Available Card
Groups must be formed starting from the smallest available card value to ensure consecutive sequences work correctly. Starting from an arbitrary card can leave smaller cards stranded without enough consecutive neighbors to form a valid group. Always process cards in sorted order or use a min-heap to find the smallest available value.
Failing to Decrement Counts Properly
When forming a group, each card in the consecutive sequence must have its count decremented. A common bug is forgetting to decrement or decrementing the wrong key, which causes cards to be reused or leaves cards unused. Additionally, when a card's count reaches zero, it must be handled correctly to avoid checking for cards that no longer exist.
Python code example
from typing import List
from collections import Counter
class Solution:
def isNStraightHand(self, hand: List[int], groupSize: int) -> bool:
if len(hand) % groupSize != 0:
return False
count = Counter(hand)
for num in hand:
start = num
while count[start - 1]:
start -= 1
while start <= num:
while count[start]:
for i in range(start, start + groupSize):
if not count[i]:
return False
count[i] -= 1
start += 1
return True
C++ code example
class Solution {
public:
bool isNStraightHand(vector<int>& hand, int groupSize) {
if (hand.size() % groupSize != 0) return false;
unordered_map<int, int> count;
for (int num : hand) count[num]++;
for (int num : hand) {
int start = num;
while (count[start - 1] > 0) start--;
while (start <= num) {
while (count[start] > 0) {
for (int i = start; i < start + groupSize; i++) {
if (count[i] == 0) return false;
count[i]--;
}
}
start++;
}
}
return true;
}
};
Source and license
Adapted from NeetCode’s source · MIT license. Node types are supplied by LeetCode where needed.