题干信息

- 这道题很容易想到利用排序来实现
- 将nums数组前后半部分分开,将后半部分插入前半部分两两之间即可。直观上感觉这样做是对的。实际上有问题!
- 考虑当nums为[4,5,5,2]时,按上面的做法得出的结果和nums原本是一致的。而实际上nums可以按照题意变为[4,5,2,5]
IDEA1:考虑逆序插入+分类讨论
当nums.length为偶数时,考虑将Nums首先从小到大进行排序,再将nums分成大小相同的两部分。设nums.length = n,则将nums分为的第一部分为
nums[0],nums[1],⋯nums[n/2−1]nums[0],nums[1],\cdots nums[n/2 -1]nums[0],nums[1],⋯nums[n/2−1]
将nums分为的第二部分为:nums[n/2],nums[n/2+1],⋯nums[n−1]nums[n/2],nums[n/2+1],\cdots nums[n-1]nums[n/2],nums[n/2+1],⋯nums[n−1]
容易看出两者的长度是相同的。
- 如果nums[n/2]>nums[n/2−1]nums[n/2]>nums[n/2-1]nums[n/2]>nums[n/2−1]时,我们可以放心的将后一个序列插入前一个序列之间,亦即最终构成序列nums[0],nums[n/2],nums[1],nums[n/2+1]⋯nums[n−1],nums[n/2−1]nums[0],nums[n/2],nums[1],nums[n/2+1]\cdots nums[n-1],nums[n/2-1]nums[0],nums[n/2],nums[1],nums[n/2+1]⋯nums[n−1],nums[n/2−1]
- 但不能排除:nums[n/2]=nums[n/2−1]nums[n/2]=nums[n/2-1]nums[n/2]=nums[n/2−1]的情况!
- 如果按照上述思路的话[4,5,5,2][4,5,5,2][4,5,5,2]的例子就不行!
- 逆序插入可以很好的解决这一问题。将前一个序列逆序,后一个序列逆序。即最终构成的结果为
nums[n/2−1],nums[n−1],nums[n/2−2],nums[n−2],⋯nums[0],nums[n/2]nums[n/2-1],nums[n-1],nums[n/2-2],nums[n-2],\cdots nums[0],nums[n/2]nums[n/2−1],nums[n−1],nums[n/2−2],nums[n−2],⋯nums[0],nums[n/2]
下面证明为什么上述逆序插入的思路是可行的。显然当nums[n/2]>nums[n/2−1]nums[n/2]>nums[n/2-1]nums[n/2]>nums[n/2−1]时逆序插入的思路是可行的。只证明当nums[n/2]=nums[n/2−1]nums[n/2]=nums[n/2-1]nums[n/2]=nums[n/2−1]上述思路是可行的。
- 首先,我们一定有nums[n/2−1]<nums[n−1]nums[n/2-1]<nums[n-1]nums[n/2−1]<nums[n−1].若不然则nums[n/2−1]=nums[n−1]nums[n/2-1]=nums[n-1]nums[n/2−1]=nums[n−1],则由于nums是经过排序的,至少一定有nums[n−1]=nums[n−2]=⋯=nums[n/2−1]nums[n-1] = nums[n-2] = \cdots = nums[n/2 - 1]nums[n−1]=nums[n−2]=⋯=nums[n/2−1].这其中的数一共有:n−n/2+1=n/2+1n-n/2+1 = n/2+1n−n/2+1=n/2+1个数,即相等的数比nums总长度的一半还多。因此无论如何怎样排列总有两个相同的数连在一起,不可能实现本题目所示的结果,这和题目的前提矛盾!
- 类似可以证明nums[n/2−2]<nums[n−2]nums[n/2-2]<nums[n-2]nums[n/2−2]<nums[n−2]一直到nums[0]<nums[n/2]nums[0] < nums[n/2]nums[0]<nums[n/2]
奇数情况可以类似证明。
下面的AC代码将奇数情况和偶数情况合并了。是高级语言中整除运算符的特性(向下取整)。
public void wiggleSort(int[] nums) {
int[] temp = nums.clone();
Arrays.sort(temp);
for(int i = 0;i<nums.length;i+=2)
{ //这里的(nums.length - 1)/2实际上是将两种情况都合并了!!
nums[i] = temp[(nums.length - 1)/2 - i/2];
}
for(int i = 1;i<nums.length;i+=2)
{
nums[i] = temp[nums.length - 1 - i / 2];
}
}
IDEA2:优化1-桶排序
根据题目所示的条件:0 <= nums[i] <= 5000。可以考虑使用桶排序,复杂度为O(n)O(n)O(n)
这篇博客探讨了一种特殊的数组排列问题,即如何将一个有序数组以交错方式重新排列。作者首先提出了一个直观但不完全正确的解决方案,然后通过逆序插入和分类讨论的方法解决了这个问题。在偶数长度的数组中,通过比较中间两个元素并逆序插入,确保了交错效果。同时,博客还提到了桶排序作为进一步优化的可能性,以实现线性时间复杂度的解法。
895

被折叠的 条评论
为什么被折叠?



