324. Wiggle Sort II
2016-07-11 22:54
441 查看
Given an unsorted array
Example:
(1) Given
(2) Given
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?
看成一个序列的穿插,如果把一个序列排序以后分成大的一部分和小的一部分,如果用这两部分子数组穿插生成新的数组,必定满足一个大一个小的要求。可能出现的问题是中间的元素可能是一样大的,这样分割成的小数组末尾和大数组开头元素有可能会相同,总体的思路要从两个子数组的两边交替取值。
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
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.
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
The code is the following:
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); }
相关文章推荐
- 使用HorizontalListView,实现左右滑动时,有箭头提示,到达端点时,箭头消失。
- Android利用canvas画各种图形
- 配置ubuntu16.04下Theano使用GPU运行程序的环境
- hdu 1598 极品飞车 (并查集+贪心)
- Simulator进行模拟定位
- C++单例模式
- ecshop 站群,多模板,多域名共用一个后台
- 基于JavaScript的字符串暴力匹配算法(BF算法)
- delete
- Windows系统重装问题
- java的一路发展历程!
- git常见命令与github仓库的使用
- 学习单片机关于转换进制的问题
- ARM 汇编指令(更新中)
- iOS10.0 & Swift 3.0 对于升级项目的建议
- PHP检测移动设备类mobile detection使用实例
- 3.1.4.3 段页式管理方式
- 第一篇博客,写给自己,7.11
- Mysql5.7启动不了又没报错的问题
- 大幅度增加和改良了input元素的种类