If we sort the array, adjacent elements become close in value, which makes it more likely for an element to be the average of its neighbors. To avoid this, we can interleave elements from the small and large ends of the sorted array. By alternating between picking from the front (small) and back (large), we create a pattern where neighbors differ significantly, preventing any element from being the exact average of its neighbors.
l) and one at the end (r) of the sorted array.l (small values) and r (large values).Instead of building a new array, we can rearrange in place. After sorting, if we swap every pair of adjacent elements at odd indices with their preceding element, we create a zigzag pattern. This ensures that each element at an odd index is a local maximum or minimum relative to its neighbors, which prevents any element from being the average of its neighbors.
i with the element at index i - 1.We can fix violations as we find them without sorting first. If an element equals the average of its neighbors, swapping it with an adjacent element will break that relationship. By making one forward pass and one backward pass, we can fix all violations. The forward pass handles cases where swapping with the next element helps, and the backward pass catches any remaining issues.
1 to n-2.n-2 to 1.class Solution:
def rearrangeArray(self, nums: List[int]) -> List[int]:
n = len(nums)
for i in range(1, n - 1):
if 2 * nums[i] == (nums[i - 1] + nums[i + 1]):
nums[i], nums[i + 1] = nums[i + 1], nums[i]
for i in range(n - 2, 0, -1):
if 2 * nums[i] == (nums[i - 1] + nums[i + 1]):
nums[i], nums[i - 1] = nums[i - 1], nums[i]
return numsA valid arrangement alternates between increasing and decreasing. We can enforce this pattern in a single pass by tracking whether the next step should increase or decrease. Starting from the relationship between the first two elements, we alternate the expected direction. If the actual relationship violates the expected direction, we swap to fix it.
nums[0] < nums[1] (increasing) or not.1 to n-2.nums[i] < nums[i+1], or if decreasing and nums[i] > nums[i+1], swap nums[i] and nums[i+1].class Solution:
def rearrangeArray(self, nums: List[int]) -> List[int]:
increase = nums[0] < nums[1]
for i in range(1, len(nums) - 1):
if ((increase and nums[i] < nums[i + 1]) or
(not increase and nums[i] > nums[i + 1])
):
nums[i], nums[i + 1] = nums[i + 1], nums[i]
increase = not increase
return numsWhen fixing a violation by swapping, the swap might create a new violation at the previous position. A single forward pass may not catch all cases, which is why some solutions use both forward and backward passes.
# Wrong: only forward pass may leave violations
for i in range(1, n - 1):
if 2 * nums[i] == nums[i-1] + nums[i+1]:
nums[i], nums[i+1] = nums[i+1], nums[i]
# A backward pass is also neededUsing division to check if an element equals the average of its neighbors can introduce floating-point precision issues. Instead, multiply both sides by 2 to avoid division entirely.
# Wrong: floating-point comparison
if nums[i] == (nums[i-1] + nums[i+1]) / 2:
# Correct: integer comparison
if 2 * nums[i] == nums[i-1] + nums[i+1]:The check only applies to elements with both neighbors (indices 1 through n-2). Applying the average check to the first or last element causes index out of bounds errors.
# Wrong: starts at index 0
for i in range(len(nums) - 1):
if 2 * nums[i] == nums[i-1] + nums[i+1]: # i=0 causes nums[-1] access