当 n 为偶数时:因为 nums[i]<nums[i+x],所以一定满足 nums[i]<nums[i+x],nums[i−1]<nums[i+x],因此我们将 nums[i+x] 插入到 nums[i]与nums 之间,比如我们可以按照以下顺序进行插入:
nums[x],nums[0],nums[x+1],nums[1],⋯,nums[n−2−x],nums[n−1],nums[n−1−x]
然后将上述序列进行反转:
nums[n−1−x],nums[n−1],nums[n−2−x],⋯,nums[1],nums[x+1],nums[0],nums[x]
即可得到合法的摆动排序。比如序列当前序列为 [0,1,2,3,4,5],我们可以得到序列 [3,0,4,1,5,2],然后将其反转即为 [2,5,1,4,0,3]。
当 n 为奇数时:此时情况稍微复杂一些,此时我们需要证明当满足 i>0 时,nums[i]<nums[i+x−1]。此时我们可以用反证法来证明。假设存在 i 且满足 i>0,且满足 nums[i]=nums[i+x−1] 时,则此时按照排序的规则可知 nums[i]=nums[i+1]=nums[i+2]=⋯=nums[i+x−1],此时数组中一共有 x 个相同的元素。由于这 x 个元素不能互相相邻,按照摆动排序的规则,这 x 个相同的元素只能放在数组的偶数位的索引中(数组索引以 0 为起始),只能放置在 0,2,4,⋯,n−1 位置上,否则就会出现相邻元素相等,而此时由于 nums[0] 最小,因此它只能放置在偶数位的索引上,而数组中的偶数位的索引最多只有 x 个,这就必然会导致矛盾,nums[0] 无法摆放。因此,当满足 i>0 时,nums[i]=nums[i+x−1],也即 nums[i]<nums[i+x−1]。根据上述的结论我们可以得到 nums[i]<nums[i+x],nums[i+1]<nums[i+x]。因此我们将 nums[i+x] 插入到 nums[i] 与 nums[i+1]之间,比如我们可以按照以下顺序进行插入:
nums[0],nums[x],nums[1],⋯,nums[n−1−x],nums[n−1],nums[n−x]
比如序列当前序列为 [0,1,2,3,4],我们可以返回序列 [0,3,1,4,2]。同理我们将上述序列进行反转后,该序列仍然为符合要求的摆动排序。
var wiggleSort = function(nums) {
const arr = nums.slice()
arr.sort((a, b) => a - b)
const n = nums.length
const x = Math.floor((n + 1) / 2)
for (let i = 0, j = x - 1, k = n - 1
nums[i] = arr[j]
if (i + 1 < n) {
nums[i + 1] = arr[k]
}
}
}