Neetcode 150 - Hand of Straights

1. Input, Output, Contrains

  1. Input:
  • hand: List[int] — cards in hand.
  • groupSize: int — number of cards per group.
  1. Output:
  • Return True if the hand can be rearranged into groups of groupSize consecutive numbers.
  • Return False otherwise.
  1. 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