Introduction
LeetCode 769, Max Chunks To Make Sorted, is an interesting array partitioning problem.
The array is a permutation of numbers from 0 to n - 1. The goal is to divide the array into multiple contiguous chunks, sort each chunk independently, and then join all the sorted chunks together.
The challenge is to find the maximum number of chunks for which the final concatenated array becomes completely sorted.
For example:
The array can be divided as:
After sorting every chunk:
The final array is:
Therefore, the answer is 4.
The given solution approaches the problem using recursion and backtracking to generate possible partitions and then checks which partitions produce a sorted array.
Question Link
LeetCode 769 – Max Chunks To Make Sorted
Understanding the Problem
The important word in the problem is chunks.
A chunk must contain consecutive elements from the original array.
For example:
Possible partition:
After sorting:
Combining them gives:
which is not sorted.
So this partition is invalid.
The task is not simply to split the array into as many pieces as possible. Every chosen partition must satisfy the condition that sorting each piece independently produces the globally sorted array.
Approach: Recursion + Backtracking
The given solution tries every possible way of partitioning the array.
At every index, it considers every possible ending position for the current chunk.
For example:
Starting from index 0, possible first chunks are:
For each choice, recursion continues from the next index.
This generates different partition configurations such as:
Each complete partition is then checked to determine whether it produces a sorted array.
Generating the Chunks
The recursive function is:
Here:
indrepresents the current starting index.chunkstores the chunks selected so far.
The loop:
tries every possible ending point for the current chunk.
The important part is:
Once a chunk from ind to i has been selected, the next chunk must begin at i + 1.
Creating a Chunk
The subar() method creates a list containing the elements between two indices.
For example:
produces:
Checking a Partition
Once a complete partition has been generated, the vali() method checks whether it is valid.
First, every chunk is sorted:
Then all sorted chunks are concatenated into one list:
Finally, the resulting array is checked to see whether it is globally sorted.
If no decreasing pair exists, the partition is valid.
Java Solution
Dry Run
Consider:
One of the partitions generated by recursion is:
The chunks are individually sorted:
After concatenation:
The resulting array is sorted, so the partition is valid.
It contains:
The recursion also examines partitions with fewer chunks, such as:
Among all valid partitions, the solution keeps the maximum number of chunks using:
Therefore:
Why Does the Maximum Number of Chunks Matter?
A partition with fewer chunks can still produce the sorted array.
For example:
can be split as:
After sorting:
which produces:
So this is valid.
But it is not the maximum because:
also works and gives more chunks.
Therefore, every valid partition cannot simply be accepted—the number of chunks must also be maximized.
Complexity Analysis
The number of ways to split an array of length n into contiguous chunks is:
because every gap between two elements can either contain a partition or not.
For example, with:
there are two gaps:
Each gap has two choices, giving:
possible partitions.
For every complete partition, the solution also sorts the chunks and constructs the resulting array.
Therefore, the overall complexity is exponential.
Time Complexity: Approximately O(2^n × n log n)
Space Complexity: Approximately O(n × 2^n) in the worst case because many partition configurations and temporary lists are generated.
Since the given constraint is only:
this brute-force approach is feasible.
A Better Observation
Although recursion works for the small constraint, this problem has a much simpler O(n) greedy solution.
The key observation comes from the fact that the array is a permutation of:
Suppose the current chunk ends at index i.
If the maximum value seen so far is exactly i, then the current elements contain exactly the values that should occupy positions 0 through i.
Therefore, the chunk can safely end at this position.
For example:
Track the maximum:
Whenever:
a new chunk can be created.
This happens at:
So the answer is:
The optimized implementation is:
This reduces the complexity to:
Time Complexity: O(n)
Space Complexity: O(1)
Interview Tip
When a problem says the array is a permutation from 0 to n-1, that property is usually extremely important.
Instead of immediately trying to generate all possibilities, look for a relationship between:
- the current index
- the values seen so far
- the final sorted position
For this problem, the condition:
means that the current portion contains exactly the values needed for that prefix of the sorted array.
That single observation turns an exponential backtracking solution into a linear greedy solution.
Conclusion
LeetCode 769 is a good example of how the same problem can be approached at different levels.
The recursive solution explores every possible contiguous partition, sorts each chunk, and checks whether the final result is sorted. It is straightforward and works well under the small constraint n <= 10.
However, the permutation property provides a much stronger observation. Whenever the maximum value seen so far equals the current index, a chunk can safely end there.
That leads to a simple:
greedy solution.
The main lesson is to first understand the brute-force structure, then look for properties in the input that can eliminate the need to explore every possibility.




