leetcode324. 摆动排序 II

传送门

题目:给定一个无序的数组 nums,将它重新排列成 nums[0] < nums[1] > nums[2] < nums[3]… 的顺序。
说明: 你可以假设所有输入都会得到有效的结果。

输入: nums = [1, 5, 1, 1, 6, 4]       
输出: 一个可能的答案是 [1, 4, 1, 5, 1, 6]
原理:
首先,我们可以很容易想到一种简单的解法:将数组进行排序,
然后从中间位置进行等分(如果数组长度为奇数,则将中间的元素分到前面),

然后将两个数组进行穿插。
例如:对于数组[1, 5, 2, 4, 3],我们将其排序,得到[1, 2, 3, 4, 5],
然后将其分割为[1, 2, 3][4, 5],对两个数组进行穿插,得到[1, 4, 2, 5, 3]。

但是这一解法有一个问题,例如,对于数组[1, 2, 2, 3],按照这种做法求得的结果仍为[1, 2, 2, 3]。
如果题目不要求各元素严格大于或小于相邻元素,那么这一解法是符合要求的,
但题目要求元素相互严格大于或小于

在下文中定义前半部分为数组A,后半部分数组B。
显然,出现上述现象是因为nums中存在重复元素。实际上,由于穿插之后,相邻元素必来自不同子数组,

所以,出现上述情况其实是因为数组A和数组B出现了相同元素,我们用r来表示这一元素。
而且我们可以很容易发现,如果A和B都存在r,那么r一定是A的最大值,B的最小值,
这意味着r一定出现在A的尾部,B的头部。

要解决这一问题,我们需要使A的r和B的r在穿插后尽可能分开。一种可行的办法是将A和B反序:

例如,对于数组[1,1,2,2,2,3],分割为[1,1,2][2,2,3],分别反序后得到[2, 1, 1][3, 2, 2],
此时2在A头部,B尾部,穿插后就不会发生相邻了。

由于需要使用排序,时间复杂度为O(NlogN),由于需要存储A和B,所以空间复杂度为O(N)。

流程:

1.	把原数组nums排序
2.	从左到右遍历 拷贝数组copy 的奇数位置, 从右往左把nums的值依次放入奇数位置
3.	把nums剩下的 还是从右往左 放入  copy数组从左往右的偶数位置
		public void wiggleSort(int[] nums) {
			Arrays.sort(nums);
			if (nums.length <= 2) return;
			
			int[] copy = new int[nums.length];
            
             int mid = nums.length >> 1;
            
			int index = nums.length - 1;
			for (int odd = 1; odd < copy.length; odd += 2) 
				copy[odd] = nums[index--];
             for (int even = 0; even < copy.length; even += 2) 
             	copy[even] = nums[index--];
             	
			index = 0;
			for (int num : copy) nums[index++] = num;
	    }

方法2. 时间空间优化 没有做

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值