您的位置:首页 > 其它

324. Wiggle Sort II

2016-07-11 22:54 441 查看
Given an unsorted array 
nums
, reorder it such that 
nums[0]
< nums[1] > nums[2] < nums[3]...
.

Example:

(1) Given 
nums = [1, 5, 1, 1, 6, 4]
, one possible answer is 
[1,
4, 1, 5, 1, 6]


(2) Given 
nums = [1, 3, 2, 2, 3, 1]
, one possible answer is 
[2,
3, 1, 3, 1, 2]
.

Note:

You may assume all input has valid answer.

Follow Up:

Can you do it in O(n) time and/or in-place with O(1) extra space?

看成一个序列的穿插,如果把一个序列排序以后分成大的一部分和小的一部分,如果用这两部分子数组穿插生成新的数组,必定满足一个大一个小的要求。可能出现的问题是中间的元素可能是一样大的,这样分割成的小数组末尾和大数组开头元素有可能会相同,总体的思路要从两个子数组的两边交替取值。

public static void wiggleSort(int[] nums)
{
int len=nums.length;
if(len<2)
return ;

Arrays.sort(nums);
int[] arr=new int[len];
int cnt=0;

if(len%2==0)
{
if(arr[len/2-1]!=arr[len/2])
for(int i=0,j=len/2;i<len/2;i++,j++)
{
arr[cnt++]=nums[i];
arr[cnt++]=nums[j];
}
else {
for(int i=len/2-1,j=len-1;i>=0;i--,j--)
{
arr[cnt++]=nums[i];
arr[cnt++]=nums[j];
}
}
}
else
{
arr[cnt++]=nums[len/2];

for(int i=len/2-1,j=len-1;i>=0;i--,j--)
{
arr[cnt++]=nums[j];
arr[cnt++]=nums[i];
}
}

System.arraycopy(arr, 0, nums, 0, len);
}


O(N)的方法
https://discuss.leetcode.com/topic/41464/step-by-step-explanation-of-index-mapping-in-java
The virtual index idea in the post https://leetcode.com/discuss/77133/o-n-o-1-after-median-virtual-indexing

is very brilliant! However, it takes me a while to understand why and how it works. There is no 'nth_element' in Java, but you can use 'findKthLargest' function from "https://leetcode.com/problems/kth-largest-element-in-an-array/"
to get the median element in average O(n) time and O(1) space.

Assume your original array is {6,13,5,4,5,2}. After you get median element, the 'nums' is partially sorted such that the first half is larger or equal to the median, the second half is smaller or equal to the median, i.e
13   6   5   5   4   2

M


In the post https://leetcode.com/discuss/76965/3-lines-python-with-explanation-proof, we have learned that , to get wiggle sort, you
want to put the number in the following way such that

(1) elements smaller than the 'median' are put into the last even slots

(2) elements larger than the 'median' are put into the first odd slots

(3) the medians are put into the remaining slots.
Index :       0   1   2   3   4   5
Small half:   M       S       S
Large half:       L       L       M


M - Median, S-Small, L-Large. In this example, we want to put {13, 6, 5} in index 1,3,5 and {5,4,2} in index {0,2,4}

The index mapping, (1 + 2*index) % (n | 1) combined with 'Color sort', will do the job.

After selecting the median element, which is 5 in this example, we continue as the following
Mapped_idx[Left] denotes the position where the next smaller-than median element  will be inserted.
Mapped_idx[Right] denotes the position where the next larger-than median element  will be inserted.

Step 1:
Original idx: 0    1    2    3    4    5
Mapped idx:   1    3    5    0    2    4
Array:        13   6    5    5    4    2
Left
i
Right
nums[Mapped_idx[i]] = nums[1] = 6 > 5, so it is ok to put 6 in the first odd index 1. We increment i and left.

Step 2:
Original id
d6e8
x: 0    1    2    3    4    5
Mapped idx:   1    3    5    0    2    4
Array:        13   6    5    5    4    2
Left
i
Right
nums[3] = 5 = 5, so it is ok to put 6 in the index 3. We increment i.

Step 3:
Original idx: 0    1    2    3    4    5
Mapped idx:   1    3    5    0    2    4
Array:        13   6    5    5    4    2
Left
i
Right
nums[5] = 2 < 5, so we want to put it to the last even index 4 (pointed by Right). So, we swap nums[Mapped_idx[i]] with nums[Mapped_idx[Right]], i.e. nums[5] with nums[4], and decrement Right.

Step 4:
Original idx: 0    1    2    3    4    5
Mapped idx:   1    3    5    0    2    4
Array:        13   6    5    5    2    4
Left
i
Right
nums[5] = 4 < 5, so we want to put it to the second last even index 2. So, we swap nums[5] with nums[2], and decrement Right.

Step 5:
Original idx: 0    1    2    3    4    5
Mapped idx:   1    3    5    0    2    4
Array:        13   6    4    5    2    5
Left
i
Right
nums[5] = 5 < 5, it is ok to put it there, we increment i.

Step 6:
Original idx: 0    1    2    3    4    5
Mapped idx:   1    3    5    0    2    4
Array:        13   6    4    5    2    5
Left
i
Right
nums[0] = 13 > 5, so, we want to put it to the next odd index which is 3 (pointed by 'Left'). So, we swap nums[0] with nums[3], and increment 'Left' and 'i'.

Step Final:
Original idx: 0    1    2    3    4    5
Mapped idx:   1    3    5    0    2    4
Array:        5    6    4    13   2    5
Left
i
Right
i > Right, we get the final wiggle array 5 6 4 13 2 5 !


The code is the following:
public void wiggleSort(int[] nums) {
int median = findKthLargest(nums, (nums.length + 1) / 2);
int n = nums.length;

int left = 0, i = 0, right = n - 1;

while (i <= right) {

if (nums[newIndex(i,n)] > median) {
swap(nums, newIndex(left++,n), newIndex(i++,n));
}
else if (nums[newIndex(i,n)] < median) {
swap(nums, newIndex(right--,n), newIndex(i,n));
}
else {
i++;
}
}

}

private int newIndex(int index, int n) {
return (1 + 2*index) % (n | 1);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: