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 = [3,5,2,1,6,4]
Output: [3,5,1,6,2,4]Explanation: [1,6,2,5,3,4] is also accepted.
Example 2:
Input: nums = [6,6,5,6,3,8]
Output: [6,6,5,6,3,8]Constraints:
1 <= nums.length <= 5 * 10^40 <= nums[i] <= 10^4nums.Follow Up: Could you solve the problem in O(n) time complexity?
Before attempting this problem, you should be comfortable with:
For a wiggle sorted array, odd indices should hold larger values and even indices should hold smaller values relative to their neighbors. Using a max-heap, we can extract elements in descending order and strategically place the largest values at odd indices first, then fill even indices with the remaining values. This ensures the wiggle property is maintained.
1, 3, 5, ...) and pop from the heap to assign values. These positions get the larger elements.0, 2, 4, ...) and pop remaining elements from the heap.class Solution:
def wiggleSort(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
maxHeap = []
for num in nums:
heapq.heappush(maxHeap, -num)
n = len(nums)
for i in range(1, n, 2):
nums[i] = -heapq.heappop(maxHeap)
for i in range(0, n, 2):
nums[i] = -heapq.heappop(maxHeap)After sorting the array, we can create the wiggle pattern by swapping adjacent pairs starting from index 1. When we swap elements at positions 1 and 2, then 3 and 4, and so on, we create local peaks at odd indices. This works because after sorting, swapping pushes the slightly larger element to the odd index position.
1, incrementing by 2 each time.We can achieve wiggle sort in a single pass by observing the required relationship at each index. At odd indices, the element should be greater than or equal to its predecessor. At even indices, the element should be less than or equal to its predecessor. If these conditions are violated, we simply swap with the previous element to fix the relationship locally without affecting previously processed elements.
1.class Solution:
def wiggleSort(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
for i in range(1, len(nums)):
if ((i % 2 == 1 and nums[i] < nums[i - 1]) or
(i % 2 == 0 and nums[i] > nums[i - 1])
):
nums[i], nums[i - 1] = nums[i - 1], nums[i]This is an optimized version of the greedy approach using XOR for condition checking. The key observation is that we need to swap when the parity of the index does not match whether the current element is greater than the previous. Using XOR on these two boolean conditions elegantly captures when a swap is needed.
1.i % 2) and whether the current element is greater than the previous (nums[i] > nums[i-1]).true (they differ), swap the current element with the previous one.Wiggle Sort requires nums[0] <= nums[1] >= nums[2] <= nums[3]... (non-strict inequalities), while Wiggle Sort II requires strict inequalities. Using the wrong condition will fail test cases with duplicate elements.
# This problem (Wiggle Sort): allows equality
# nums[i] <= nums[i+1] for odd i
# nums[i] >= nums[i+1] for even i
# Wiggle Sort II: requires strict inequality
# nums[i] < nums[i+1] for odd i (different problem!)The greedy approach compares each element with its previous element (i-1), not the next element (i+1). Swapping with the wrong neighbor breaks the already-established wiggle pattern.
# Wrong: comparing with next element and swapping forward
if i % 2 == 1 and nums[i] < nums[i + 1]:
nums[i], nums[i + 1] = nums[i + 1], nums[i]
# Correct: comparing with previous element
if i % 2 == 1 and nums[i] < nums[i - 1]:
nums[i], nums[i - 1] = nums[i - 1], nums[i]The greedy approach needs to compare each element with its predecessor, so the loop must start at index 1. Starting at 0 causes an index-out-of-bounds error when accessing nums[i - 1].
# Wrong: causes index error at nums[-1]
for i in range(len(nums)):
if nums[i] > nums[i - 1]: # i=0 gives nums[-1]
# Correct: start from index 1
for i in range(1, len(nums)):
if nums[i] > nums[i - 1]: