Problem 1296

Abstract / Summary

Given an array and a number, determine if it can be divided into groups of consecutive numbers of size k.

Note

The full problem description, including helpful examples, can be found on LeetCode.

Python 1296.py

class Solution:
    def isPossibleDivide(self, nums: List[int], k: int) -> bool:
        if k == 1:
            return True
        if k > len(nums):
            return False

        freq = defaultdict(int)
        for n in nums:
            freq[n] += 1

        keys = list(sorted(freq))
        for f in keys:
            need = freq[f]
            if need > 0:
                for i in range(f, f + k):
                    freq[i] -= need
                    if freq[i] < 0:
                        return False

        return True
21 lines | 559 bytes | submitted December 6, 2023 | GitHub   tab size 4 | low complexity

Difficulty

This problem is ranked as
easy medium hard

and has an acceptance rate of about 59% (200k+ submissions).

Typical patterns to solve this problem:
  • Array
  • Greedy
  • Hash Table
  • Sorting
I solved 663 easy, 1250 medium and 309 hard problems

AI Disclaimer

Every single line of code was written by me, 100% from scratch, between August 2023 and August 2024.
However, two years later I set up this website and used various AI tools to generate most of the walkthrough / explanations below.

See this dedicated page for more details.
LeetCode profile | GitHub repo

Code Walkthrough

Overview

The provided implementation solves the problem of determining whether an integer array can be partitioned into groups of size k such that each group consists of consecutive numbers. The algorithm follows a greedy strategy: it processes the numbers in ascending order, repeatedly extracting the smallest available value and attempting to build a consecutive block of length k starting from that value. If at any point the required count for a number becomes negative, the function concludes that a valid division is impossible and returns False; otherwise it returns True after all numbers have been successfully allocated.

Core Logic

Early exit conditions

The function begins with two simple checks that handle trivial scenarios without further processing.

if k == 1:
    return True
if k > len(nums):
    return False

When k equals 1, any array can be divided into single-element groups, so the answer is always True. Conversely, if the desired group size exceeds the total number of elements, forming even a single group is impossible, and the function immediately returns False.

Frequency map construction

A frequency dictionary is built to count occurrences of each distinct integer in the input list.

freq = defaultdict(int)
for n in nums:
    freq[n] += 1

Using defaultdict(int) ensures that missing keys default to zero, simplifying the increment operation. This map enables constant-time look-ups for the remaining count of any value during the greedy extraction phase.

Sorted key iteration

The distinct numbers are sorted to guarantee that the algorithm always starts building groups from the smallest available element.

keys = list(sorted(freq))
for f in keys:
    need = freq[f]
    if need > 0:
        # attempt to form a block starting at f

Iterating over the sorted keys preserves the natural order required for consecutive groups. The variable need captures how many copies of the current smallest number still need to be placed into groups.

Forming consecutive blocks

If need is positive, the algorithm attempts to create need groups that each begin with the current number f. For each integer in the interval [f, f + k), the required count is decreased by need.

for i in range(f, f + k):
    freq[i] -= need
    if freq[i] < 0:
        return False

The inner loop walks through the k consecutive values that would complete each group. Subtracting need from each entry reflects the consumption of those numbers across all groups that start at f. The moment any frequency drops below zero, it indicates that the current number does not have enough copies to satisfy all pending groups, and the function aborts with False.

Successful completion

If the outer loop finishes without triggering a negative frequency, every number has been allocated to a valid consecutive block, and the function returns True.

return True

Edge Cases Handled

The implementation explicitly addresses several boundary conditions:

  • Single-element groups - The k == 1 shortcut ensures immediate success without further computation.
  • Group size larger than the array - The k > len(nums) guard prevents unnecessary work when division is mathematically impossible.
  • Repeated values - By storing counts in freq, the algorithm correctly handles inputs where the same number appears multiple times, allowing it to form several groups that share the same starting value.
  • Missing intermediate numbers - During block formation, if any integer in the required consecutive range is absent (frequency defaults to zero), the subtraction will produce a negative count, causing an early False return. This captures cases where the input lacks the necessary continuity.
  • Negative numbers - The sorting and frequency map operate on the raw integer values, so the algorithm works equally well for negative numbers, as long as they appear in the input list.

Performance Optimizations

Several design choices contribute to efficient execution:

  • Early termination - The two initial checks eliminate work for trivial inputs, saving time on large arrays that meet those conditions.
  • Use of defaultdict - This avoids explicit existence checks when updating frequencies, reducing overhead in the counting loop.
  • Single pass over sorted keys - By iterating over each distinct value exactly once and performing the necessary adjustments in place, the algorithm avoids repeated scanning of the entire array.
  • In-place frequency updates - Modifying the freq dictionary directly eliminates the need for auxiliary data structures to track used elements, conserving memory and keeping the inner loop tight.
  • Immediate failure detection - The moment a negative frequency is observed, the function returns, preventing further unnecessary iterations.

These aspects together ensure that the solution scales well with the size of the input while maintaining clear and concise logic.

written by openai gpt

ELI5 - Simplified Explanation

Imagine a big pile of numbered building blocks. The goal is to organize these blocks into small groups so that every group has exactly the right number of blocks in a row. For example, if the special number is three, a group could have a four, a five, and a six.

The first part of the code checks if the groups are small enough to be possible. If you are asked to make a group that is bigger than the number of blocks you have, that cannot happen. If you only need groups of one, that is always fine because every block can be its own group.

Next, the code looks at all the blocks and counts how many of each number are in the pile. It keeps these counts in a list so it knows exactly what is available. It sorts the numbers from smallest to largest to make everything neat and tidy.

Finally, the code goes through each number one by one. If it sees a number that needs to be part of a group, it tries to find the next numbers that go with it to finish the set. It subtracts one from the count of those blocks as it builds the groups. If it ever finds that it does not have enough blocks to finish a set, it knows the task cannot be done.

written by google gemini

Code Quality

Several LLMs ranked my code quality on a scale from 1 (very poor) to 10 (outstanding):
n = 26 | median = 7 | μ = 7.08 | σ = 1.38

Complexity Analysis

not analyzed yet

Other Solutions

I wrote a basic crawler to find other solutions to that problem.
Obviously, I did that after I solved the problem myself.

In general, AlgoMonster and WalkCCC solutions are high-quality and always worth a look.
I haven't checked most of the other solutions, but they might be helpful as well.

And of course, the LeetCode forum is always a good place (or even the best) to look for alternative approaches.

(click on a column header to sort the table)
author
author solutions
www AlgoMonster C++ Python Java TS
WalkCCC C++ Python Java
leetcode.ca C++ Python Java Go TS
MemoryLimitExceeded C++ Python
Progiez C++ Python Java
github BigEggStudy C#
black-shadows C++
charles-wangkai Java
fsq C++
Garvit244 Python
halfrost Go
JoshCrozier JS
keineahnung2345 C++
lkwq007 Python
shreymehul C#
suxrobGM C#
varunu28 Java
wisdompeak C++
AlgoMonster C++, Python, Java, TypeScript
WalkCCC C++, Python, Java
leetcode.ca C++, Go, Java, Python, TypeScript
MemoryLimitExceeded Python, C++
Progiez C++, Java, Python
BigEggStudy C#
black-shadows C++, C++
charles-wangkai Java
fsq C++
Garvit244 Python
halfrost Go
JoshCrozier JavaScript
keineahnung2345 C++
lkwq007 Python
shreymehul C#
suxrobGM C#
varunu28 Java
wisdompeak C++
30 links | 18 authors | 7 languages

Videos

6 videos   did my crawler come up with invalid videos ? drop me a line.

Similar Problems

1 similar problem

Solved On The Same Day

11 solutions   December 6, 2023

Extra

There are a few extra pages giving you some insights into my setup:
  • Tech Stack - my development environment and tools
  • AI - how AI helped me create this website (NOT solving the problems)
  • Progress - progression over time
  • Quality - code quality