Partition Array According to Given Pivot
MedPrompt
You are given a 0-indexed integer array nums and an integer pivot. Rearrange nums such that the following conditions are satisfied:
- Every element less than
pivotappears before every element greater thanpivot. - Every element equal to
pivotappears in between the elements less than and greater thanpivot. - The relative order of the elements less than
pivotand the elements greater thanpivotis maintained.- More formally, consider every
pi,pjwherepiis the new position of theithelement andpjis the new position of thejthelement. Ifi < jand both elements are smaller (or larger) thanpivot, thenpi < pj.
- More formally, consider every
Return nums after the rearrangement.
Example 1:
Input: nums = [9,12,5,10,14,3,10], pivot = 10
Output: [9,5,3,10,10,12,14]
Explanation:
The elements 9, 5, and 3 are less than the pivot so they are on the left side of the array.
The elements 12 and 14 are greater than the pivot so they are on the right side of the array.
The relative ordering of the elements less than and greater than pivot is also maintained. [9, 5, 3] and [12, 14] are the respective orderings.Example 2:
Input: nums = [-3,4,3,2], pivot = 2
Output: [-3,2,4,3]
Explanation:
The element -3 is less than the pivot so it is on the left side of the array.
The elements 4 and 3 are greater than the pivot so they are on the right side of the array.
The relative ordering of the elements less than and greater than pivot is also maintained. [-3] and [4, 3] are the respective orderings.
Constraints:
1 <= nums.length <= 105-106 <= nums[i] <= 106pivotequals to an element ofnums.
Approaches
2 approaches with complexity analysis and trade-offs.
This is a straightforward approach where we iterate through the input array three separate times. Each pass is responsible for collecting elements belonging to one category (less than, equal to, or greater than the pivot). We use an auxiliary array to build the result. By iterating through the input array in its original order for each category, we naturally preserve the relative ordering of the elements.
Algorithm
- Create a new result array
ansof the same size asnums. - Initialize an index
i = 0for theansarray. - First pass: Iterate through
nums. For eachnum < pivot, add it toans[i]and incrementi. - Second pass: Iterate through
nums. For eachnum == pivot, add it toans[i]and incrementi. - Third pass: Iterate through
nums. For eachnum > pivot, add it toans[i]and incrementi. - Return
ans.
Walkthrough
The core idea is to create a new array and fill it sequentially. We first fill it with all elements smaller than the pivot, then with all elements equal to the pivot, and finally with all elements greater than the pivot.
The algorithm proceeds as follows:
- Create a new integer array
resultwith the same length asnums. - Initialize a pointer,
index, to 0. This pointer will keep track of the next available position in theresultarray. - First Pass (Less than pivot): Iterate through
numsfrom left to right. If an elementnumis less thanpivot, place it atresult[index]and incrementindex. - Second Pass (Equal to pivot): Iterate through
numsagain. If an elementnumis equal topivot, place it atresult[index]and incrementindex. - Third Pass (Greater than pivot): Iterate through
numsa final time. If an elementnumis greater thanpivot, place it atresult[index]and incrementindex. - After these three passes, the
resultarray will contain the partitioned elements in the correct, stable order. Returnresult.
Here is a code snippet demonstrating this approach:
class Solution { public int[] partitionArray(int[] nums, int pivot) { int n = nums.length; int[] result = new int[n]; int index = 0; // 1. Pass for elements less than pivot for (int num : nums) { if (num < pivot) { result[index++] = num; } } // 2. Pass for elements equal to pivot for (int num : nums) { if (num == pivot) { result[index++] = num; } } // 3. Pass for elements greater than pivot for (int num : nums) { if (num > pivot) { result[index++] = num; } } return result; }}Complexity
Time
O(N), where N is the number of elements in `nums`. We iterate through the array three times, so the total time is O(N) + O(N) + O(N) = O(N).
Space
O(N), where N is the number of elements in `nums`. We use an auxiliary array of size N to store the result. If the output array is not considered extra space, the complexity would be O(1), but typically it is.
Trade-offs
Pros
Simple and intuitive to understand and implement.
Correctly preserves the relative order of elements within the 'less than' and 'greater than' partitions.
Cons
Requires three full traversals of the input array, which is less efficient than a single or two-pass solution in terms of constant factors.
Requires extra space proportional to the input size.
This approach improves upon the three-pass method by reducing the number of traversals to two. In the first pass, we count the number of elements that are less than the pivot and equal to the pivot. These counts allow us to calculate the exact boundaries for the three partitions in the final array. The second pass then iterates through the input array once more, placing each element directly into its correct spot in the result array.
Algorithm
- Initialize
lessCount = 0andequalCount = 0. - First pass: Iterate through
numsto countlessCount(elements< pivot) andequalCount(elements== pivot). - Define starting indices:
lessIndex = 0,equalIndex = lessCount,greaterIndex = lessCount + equalCount. - Create a new result array
ans. - Second pass: Iterate through
numsand place each elementnumintoansat the correct partition index (lessIndex,equalIndex, orgreaterIndex) and increment the corresponding index.
Walkthrough
This method is more optimized as it avoids redundant iterations.
The algorithm is as follows:
- First Pass (Counting): Traverse the
numsarray once to count the number of elements smaller than the pivot (lessCount) and the number of elements equal to the pivot (equalCount). - Determine Partition Boundaries: Use the counts to determine the starting indices for each partition in the result array.
- The 'less than' partition starts at index 0.
- The 'equal to' partition starts at index
lessCount. - The 'greater than' partition starts at index
lessCount + equalCount.
- Second Pass (Placing): Create a new
resultarray. Initialize three pointers:lessIndex = 0,equalIndex = lessCount, andgreaterIndex = lessCount + equalCount. Iterate through the originalnumsarray. For each element:- If it's less than
pivot, place it atresult[lessIndex]and incrementlessIndex. - If it's equal to
pivot, place it atresult[equalIndex]and incrementequalIndex. - If it's greater than
pivot, place it atresult[greaterIndex]and incrementgreaterIndex.
- If it's less than
- Return the
resultarray. This single placement pass ensures relative order is maintained.
Here is a code snippet for this approach:
class Solution { public int[] partitionArray(int[] nums, int pivot) { int n = nums.length; int[] result = new int[n]; int lessCount = 0; int equalCount = 0; // 1. First pass: Count elements for (int num : nums) { if (num < pivot) { lessCount++; } else if (num == pivot) { equalCount++; } } int lessIndex = 0; int equalIndex = lessCount; int greaterIndex = lessCount + equalCount; // 2. Second pass: Place elements for (int num : nums) { if (num < pivot) { result[lessIndex++] = num; } else if (num == pivot) { result[equalIndex++] = num; } else { result[greaterIndex++] = num; } } return result; }}Complexity
Time
O(N), where N is the number of elements in `nums`. We iterate through the array twice, once for counting and once for placing. The total time is O(N) + O(N) = O(N).
Space
O(N), where N is the number of elements in `nums`. We use an auxiliary array of size N to store the result.
Trade-offs
Pros
More efficient than the three-pass approach in terms of constant factors (2N vs 3N operations).
The logic is clean and directly places elements, preserving relative order.
Still relatively simple to implement.
Cons
Still requires O(N) extra space, which might be a concern for very large inputs if memory is constrained.
Solutions
Solution
class Solution { public int [] pivotArray ( int [] nums , int pivot ) { int n = nums . length ; int [] ans = new int [ n ]; int k = 0 ; for ( int x : nums ) { if ( x < pivot ) { ans [ k ++] = x ; } } for ( int x : nums ) { if ( x == pivot ) { ans [ k ++] = x ; } } for ( int x : nums ) { if ( x > pivot ) { ans [ k ++] = x ; } } return ans ; } }class Solution { public: vector < int > pivotArray ( vector < int >& nums , int pivot ) { vector < int > ans ; for ( int & x : nums ) if ( x < pivot ) ans . push_back ( x ); for ( int & x : nums ) if ( x == pivot ) ans . push_back ( x ); for ( int & x : nums ) if ( x > pivot ) ans . push_back ( x ); return ans ; } };class Solution : def pivotArray ( self , nums : List [ int ], pivot : int ) -> List [ int ]: a , b , c = [], [], [] for x in nums : if x < pivot : a . append ( x ) elif x == pivot : b . append ( x ) else : c . append ( x ) return a + b + cVideo walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.