重新排列数组,使中间元素不等于两侧邻居平均值——题解分享
题目描述
给定一个下标从 0 开始的数组 nums
,数组由若干互不相同的整数构成。我们需要对数组中的元素进行重新排列,使得重排后的数组满足以下条件:
对于数组中每个满足 1 <= i < nums.length - 1
的索引 i
,元素 nums[i]
不等于 其两侧相邻元素的平均值,即:
nums[i]≠nums[i−1]+nums[i+1]2nums[i] \neq \frac{nums[i-1] + nums[i+1]}{2}nums[i]=2nums[i−1]+nums[i+1]
换句话说,不允许存在:
nums[i]×2=nums[i−1]+nums[i+1]nums[i] \times 2 = nums[i-1] + nums[i+1]nums[i]×2=nums[i−1]+nums[i+1]
输入输出示例
示例 1:
输入:nums = [1, 2, 3, 4, 5]
输出:[1, 2, 4, 5, 3]
解释:
- i=1, nums[1]=2,两相邻元素平均值为 (1+4)/2=2.5,不等于2
- i=2, nums[2]=4,两相邻元素平均值为 (2+5)/2=3.5,不等于4
- i=3, nums[3]=5,两相邻元素平均值为 (4+3)/2=3.5,不等于5
示例 2:
输入:nums = [6, 2, 0, 9, 7]
输出:[9, 7, 6, 2, 0]
解释:
- i=1, nums[1]=7,两相邻元素平均值为 (9+6)/2=7.5,不等于7
- i=2, nums[2]=6,两相邻元素平均值为 (7+2)/2=4.5,不等于6
- i=3, nums[3]=2,两相邻元素平均值为 (6+0)/2=3,不等于2
解题分析
题目要求的条件看似复杂,但细心观察可以发现:
- 关键在于避免某个元素正好是其左右邻居的“中点”。
- 数组元素互不相同,这样避免了相邻相等的情况。
- 重新排列数组后,让相邻元素的差距拉开,避免中间元素“恰巧”是邻居均值。
解决方案核心思想
排序+交错排列
- 先排序,让元素从小到大排列。
- 将排序后的数组分成两部分:
- small:数组左半部分(较小元素)
- large:数组右半部分(较大元素)
- 将两部分元素交替排列,形成一个新的数组。
举例说明:
对于数组 [1, 2, 3, 4, 5]
,
- 排序后保持不变。
- small =
[1, 2, 3]
- large =
[4, 5]
交替排列后:
[1, 4, 2, 5, 3]
这样排列可以有效避免某元素等于左右邻居的平均值。
为什么交替排列可以满足条件?
交错排列确保了:
- 较小元素被较大元素分隔,避免中间元素成为两侧的平均值。
- 由于两组元素分别是升序排列,混合排列后的“跳跃”使得均值不可能刚好等于中间元素。
- 在实际测试中,这种方法可满足题意。
代码实现示例(Python)
from typing import List
class Solution:
def rearrangeArray(self, nums: List[int]) -> List[int]:
nums.sort()
n = len(nums)
mid = (n + 1) // 2
small = nums[:mid]
large = nums[mid:]
res = []
# 交错合并 small 和 large
for s, l in zip(small, large):
res.append(s)
res.append(l)
# 如果 small 比 large 多一个元素,加入最后一个元素
if len(small) > len(large):
res.append(small[-1])
return res
代码解析
nums.sort()
:排序数组。mid = (n + 1) // 2
:划分点,保证左半部分元素数量不小于右半部分。small = nums[:mid]
,large = nums[mid:]
:分割成两部分。- 通过
zip
交替合并两部分元素。 - 如果左半部分多一个元素,最后补充进结果中。
复杂度分析
- 时间复杂度:排序为主,
O(n log n)
,合并过程为O(n)
。 - 空间复杂度:辅助数组
small
和large
各O(n)
。
示例演示
假设输入 nums = [6, 2, 0, 9, 7]
:
- 排序后:
[0, 2, 6, 7, 9]
- small =
[0, 2, 6]
- large =
[7, 9]
- 交替合并得到
[0, 7, 2, 9, 6]
- 检查中间元素:
- i=1,7 != (0+2)/2=1
- i=2,2 != (7+9)/2=8
- i=3,9 != (2+6)/2=4
满足条件。
方法优劣比较
方法 | 时间复杂度 | 实现难度 | 适用场景 | 备注 |
---|---|---|---|---|
排序+交错排列 | O(n log n) | 低 | 数组元素互不相同,需重排 | 结构简单,效果好,常用解法 |
其他贪心策略 | 可能更复杂 | 高 | 特殊情况,可能需要更复杂处理 | 不推荐,易错且难以维护 |
总结
- 该问题可以通过对数组排序后分成两半,再交错排列的策略轻松解决。
- 这种排列避免了中间元素成为邻居元素平均值的情况。
- 代码实现简洁且高效,适用于大规模数组。