Wiggle Sort II
MEDIUMDescription
Given an integer array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]....
You may assume the input array always has a valid answer.
Example 1:
Input: nums = [1,5,1,1,6,4] Output: [1,6,1,5,1,4] Explanation: [1,4,1,5,1,6] is also accepted.
Example 2:
Input: nums = [1,3,2,2,3,1] Output: [2,3,1,3,1,2]
Constraints:
1 <= nums.length <= 5 * 1040 <= nums[i] <= 5000- It is guaranteed that there will be an answer for the given input
nums.
Follow Up: Can you do it in
O(n) time and/or in-place with O(1) extra space?Approaches
Checkout 3 different approaches to solve Wiggle Sort II. Click on different approaches to view the approach and algorithm in detail.
Linear Time In-Place Solution with Virtual Indexing
This optimal approach achieves O(N) time and O(1) space complexity, meeting the follow-up challenge. It avoids a full sort by finding the median element in linear time. Then, it uses a clever "virtual indexing" scheme to place elements correctly in-place. The idea is to partition the array into three groups: elements larger than the median, equal to the median, and smaller than the median. This partitioning is done on a "virtual" array that maps indices 0, 1, 2, ... to the desired wiggle positions 1, 3, 5, ..., 0, 2, 4, ....
Algorithm
- Find Median: Use an
O(N)average time selection algorithm (like Quickselect) to find the median element of the array. The median is the(n+1)/2-th smallest element, which separates the array into a smaller half and a larger half. - Virtual Indexing: Define a mapping function
map(i) = (1 + 2*i) % (n | 1)wherenis the array length. This function maps indices0, 1, 2, ...to the desired wiggle positions1, 3, 5, ..., 0, 2, 4, .... This places elements for the 'large' slots first, followed by elements for the 'small' slots. - 3-Way Partition: Perform a 3-way partition (Dutch National Flag algorithm) on the array in-place. Instead of accessing elements by their direct index
i, use the virtual indexmap(i). This partitions the array into three groups based on the median: elements larger than the median, elements equal to the median, and elements smaller than the median. The virtual indexing ensures they are placed into the correct final wiggle positions.
This advanced solution directly constructs the wiggle-sorted array without a full sort or an auxiliary array.
-
Median Finding: The first step is to find the value that partitions the numbers into two halves. This value is the median. We can find the
k-th smallest element in an array inO(N)average time using the Quickselect algorithm. For this problem, we need the(n+1)/2-th smallest element. -
Virtual Indexing and Partitioning: The core of the solution is to place all numbers larger than the median in the 'large' slots (odd indices) and all numbers smaller than the median in the 'small' slots (even indices). The numbers equal to the median will fill the remaining slots. This is achieved simultaneously using a single pass with the 3-way partition algorithm combined with virtual indexing. The mapping
A(i) = (1 + 2*i) % (n | 1)ensures that as we iterate throughifrom0ton-1, we are considering positions in the order ofodd_indices..., even_indices.... By partitioning based on this virtual layout, we move larger elements to the start of this virtual sequence (odd indices) and smaller elements to the end (even indices), achieving the wiggle sort in-place.
class Solution {
public void wiggleSort(int[] nums) {
int n = nums.length;
if (n <= 1) {
return;
}
// Step 1: Find the median element. The median is the (n+1)/2-th smallest element.
int median = findKthSmallest(nums, (n + 1) / 2);
// Step 2: 3-way partition using virtual indexing.
int left = 0, i = 0, right = n - 1;
while (i <= right) {
int mapped_i = mapIndex(i, n);
if (nums[mapped_i] > median) {
int mapped_left = mapIndex(left, n);
swap(nums, mapped_i, mapped_left);
left++;
i++;
} else if (nums[mapped_i] < median) {
int mapped_right = mapIndex(right, n);
swap(nums, mapped_i, mapped_right);
right--;
} else {
i++;
}
}
}
// Maps an index i to its corresponding position in the wiggle-sorted array.
private int mapIndex(int i, int n) {
// n | 1 ensures the modulus is always odd, which is key to the mapping.
return (1 + 2 * i) % (n | 1);
}
// Finds the k-th smallest element using Quickselect (O(N) average time).
private int findKthSmallest(int[] nums, int k) {
int[] temp = nums.clone(); // Use a copy to not disrupt the original array before partitioning
int targetIndex = k - 1; // Convert 1-based k to 0-based index
int left = 0, right = temp.length - 1;
while (left <= right) {
int pivotIndex = partition(temp, left, right);
if (pivotIndex == targetIndex) {
return temp[pivotIndex];
} else if (pivotIndex < targetIndex) {
left = pivotIndex + 1;
} else {
right = pivotIndex - 1;
}
}
return -1; // Should not be reached
}
// Lomuto partition scheme for Quickselect.
private int partition(int[] nums, int left, int right) {
int pivotValue = nums[right];
int storeIndex = left;
for (int i = left; i < right; i++) {
if (nums[i] < pivotValue) {
swap(nums, storeIndex, i);
storeIndex++;
}
}
swap(nums, right, storeIndex);
return storeIndex;
}
private void swap(int[] nums, int i, int j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
}
Complexity Analysis
Pros and Cons
- Optimal time complexity of O(N) on average.
- Optimal space complexity of O(1) (if Quickselect is done in-place on the original array, which is valid here).
- Satisfies the follow-up constraints of the problem.
- The logic, especially the virtual index mapping and in-place partitioning, is complex and non-intuitive.
- Implementation is error-prone. A standard Quickselect has an
O(N^2)worst-case time, though this is rare in practice.
Code Solutions
Checking out 4 solutions in different languages for Wiggle Sort II. Click on different languages to view the code.
class Solution {
public
void wiggleSort(int[] nums) {
int[] arr = nums.clone();
Arrays.sort(arr);
int n = nums.length;
int i = (n - 1) >> 1, j = n - 1;
for (int k = 0; k < n; ++k) {
if (k % 2 == 0) {
nums[k] = arr[i--];
} else {
nums[k] = arr[j--];
}
}
}
}
Video Solution
Watch the video walkthrough for Wiggle Sort II
Similar Questions
5 related questions you might find useful
Algorithms:
Patterns:
Data Structures:
Subscribe to Scale Engineer newsletter
Learn about System Design, Software Engineering, and interview experiences every week.
No spam, unsubscribe at any time.