1. Problem Summary
You are given an integer array nums.
Your task is to partition the array into two contiguous parts:
left = nums[0 ... i] right = nums[i+1 ... n-1]
such that:
- Every element in
leftis less than or equal to every element inright leftis non-emptyrightis non-empty
You must return the smallest possible size of left, meaning the smallest index i + 1.
Example:
Input: [5,0,3,8,6] Valid partition: left = [5,0,3] right = [8,6] Output: 3
2. Key Insights
Insight 1: Left must contain all values up to its max
For partition to be valid:
max(left) <= min(right)
Insight 2: We only care about minimal left size
So we should stop at earliest index where condition holds.
Insight 3: Running maximum helps define left boundary
As we scan array, we track:
globalMaxSoFar(max seen in entire scan)leftMax(max within left partition)
Insight 4: When violation occurs, expand left
If we encounter nums[i] < leftMax, then:
- Partition invalid
- Must extend left to include index i
- Update leftMax = globalMaxSoFar
This ensures future values re-evaluated against expanded left.
Insight 5: No need to precompute right minimums
One pass is enough.
3. Approach
Single pass tracking leftMax and globalMax
Steps:
- Initialize:
leftMax = nums[0] globalMax = nums[0] partitionIndex = 0 - Loop i from 1 to n-1:
- update globalMax = max(globalMax, nums[i])
- if nums[i] < leftMax:
- update partitionIndex = i
- update leftMax = globalMax
- At end, return partitionIndex + 1
PartitionIndex + 1 gives size of left part.
4. Time and Space Complexity
Time Complexity:
O(N)
Space Complexity:
O(1)
Uses only constant extra variables.
5. Java Solution
class Solution {
public int partitionDisjoint(int[] nums) {
int leftMax = nums[0];
int globalMax = nums[0];
int partitionIndex = 0;
for (int i = 1; i < nums.length; i++) {
globalMax = Math.max(globalMax, nums[i]);
if (nums[i] < leftMax) {
partitionIndex = i;
leftMax = globalMax;
}
}
return partitionIndex + 1;
}
}
6. Dry Run Examples
Example 1
Input:
[5,0,3,8,6]
Step-by-step:
- leftMax = 5, globalMax = 5
- i=1: nums[1]=0 < leftMax → partitionIndex=1, leftMax=5
- i=2: nums[2]=3 < leftMax → partitionIndex=2, leftMax=5
- i=3: nums[3]=8 → update globalMax = 8
- i=4: nums[4]=6
Final:
partitionIndex + 1 = 3
Output:
3
Example 2
Input:
[1,1,1,0,6,12]
Trace:
- leftMax=1
- nums[1]=1
- nums[2]=1
- nums[3]=0 < leftMax → partitionIndex=3, leftMax=1
- nums[4]=6 globalMax=6
- nums[5]=12 globalMax=12
Output:
4
Example 3
Input:
[1,2,3]
First element always enough because always <= right
Output:
1
Example 4
Input:
[10,5,6,7,8,9]
nums[1]=5 < 10 → extend
nums[2]=6 < 10 → extend
…
nums[5]=9 < 10 → extend
Entire left must contain all elements
Output:
6
Example 5
Input:
[2,0,1]
nums[1]=0 < 2 → extend
nums[2]=1 < 2 → extend
Output:
3
7. Why This Solution Works
- leftMax ensures left side constraint enforced
- globalMax allows safe expansion of boundary
- minimal left achieved by updating only when necessary
- greedy correctness proven by monotonic partition rule
- avoids expensive min-right preprocessing
8. Common Mistakes
- Trying to sort array (invalid because partition must be contiguous)
- Precomputing right mins using extra arrays (works but uses O(N) space)
- Confusing with two-pointer partitioning
- Returning partition index instead of size
- Forgetting left must be non-empty
