Neetcode 150 - Hand of Straights
1. Input, Output, Contrains
- Input:
hand: List[int] — cards in hand.groupSize: int — number of cards per group.
- Output:
- Return
Trueif the hand can be rearranged into groups ofgroupSizeconsecutive numbers. - Return
Falseotherwise.
- Contraints:
1 ≤ len(hand) ≤ 10⁴0 ≤ hand[i] ≤ 10⁹1 ≤ groupSize ≤ len(hand)
2. Dry run
Step 1: Sort the hand → [1,2,2,3,3,4,6,7,8]
Step 2: Build frequency map:
count = {1:1, 2:2, 3:2, 4:1, 6:1, 7:1, 8:1}
Step 3: Form groups: | Iteration | Start | Group Formed | Remaining Counts | |————|——–|—————|——————| | 1 | 1 | [1,2,3] | {2:1, 3:1, 4:1, 6:1, 7:1, 8:1} | | 2 | 2 | [2,3,4] | {6:1, 7:1, 8:1} | | 3 | 6 | [6,7,8] | {} |
✅ All groups formed successfully → Return True
3. Naive Solution
Sort the cards and repeatedly try to form valid groups starting from the smallest card still remaining.
def isNStraightHand(hand, groupSize):
if len(hand) % groupSize != 0:
return False
hand.sort()
while hand:
start = hand[0]
for num in range(start, start + groupSize):
if num not in hand:
return False
hand.remove(num) # O(N) each time
return True
Complexity:
-
Sort: O(NlogN).
-
Pick: O(N) * remove O(N) -> O(N^2)
=> Time Complexity: O(N²)
- Space Complexity: O(1)
4. Optimized Solution
from collections import Counter
def isNStraightHand(hand, groupSize):
if len(hand) % groupSize != 0:
return False
count = Counter(hand)
for card in sorted(count):
if count[card] > 0:
need = count[card]
for next_card in range(card, card + groupSize):
if count[next_card] < need:
return False
count[next_card] -= need
return True
Complexity:
-
Counting: O(N).
-
Sorted: O(UlogU) -> O(NlogN).
-
Operate: O(N) because choosing from N elements.
October 17, 2025