摆动排序 II
题目
给你一个数组nums,将它重排列如下形式
nums[0] < nums[1] > nums[2] < nums[3]….注意事项
你可以认为每个输入都有合法解样例
给出 nums = [1, 5, 1, 1, 6, 4],一种方案为 [1, 4, 1, 5, 1, 6].
给出 nums = [1, 3, 2, 2, 3, 1],一种方案为 [2, 3, 1, 3, 1, 2].挑战
O(N)时间复杂度 O(1)额外空间
题解
1.先使用快速选择算法(算法导论9.2节)获取中位数。
2.如数组长度为奇数,则将比中位数小的元素放在0,2,4,…位置,比中位数大的放在length-2,length-4,…位置。
3.如数组长度为偶数,则将比中位数小的元素放在length-2,length-4,…位置,比中位数大的依次放在1,3,5,…位置,剩余位置补中位数。
public class Solution
{
public static void wiggleSort(int[] nums)
{
int[] tem = new int[nums.length];
for (int i = 0; i < nums.length; i++)
{
tem[i] = nums[i];
}
int mid = partition(tem, 0, nums.length - 1, nums.length / 2);
int[] ans = new int[nums.length];
for (int i = 0; i < nums.length; i++)
{
ans[i] = mid;
}
int l, r;
if (nums.length % 2 == 0)
{
l = nums.length - 2;
r = 1;
for (int i = 0; i < nums.length; i++)
{
if (nums[i] < mid)
{
ans[l] = nums[i];
l -= 2;
}
else if (nums[i] > mid)
{
ans[r] = nums[i];
r += 2;
}
}
}
else
{
l = 0;
r = nums.length - 2;
for (int i = 0; i < nums.length; i++)
{
if (nums[i] < mid)
{
ans[l] = nums[i];
l += 2;
}
else if (nums[i] > mid)
{
ans[r] = nums[i];
r -= 2;
}
}
}
for (int i = 0; i < nums.length; i++)
{
nums[i] = ans[i];
}
}
public static int partition(int[] nums, int l, int r, int rank)
{
int left = l, right = r;
//将数组分割为左右两个数组,左边的小于nums[left],右边的大于nums[left](数组可能为空)
int now = nums[left];
while (left < right)
{
while (left < right && nums[right] >= now)
{
right--;
}
nums[left] = nums[right];
while (left < right && nums[left] <= now)
{
left++;
}
nums[right] = nums[left];
}
//此时nums[left]为主元,检查主元是否就是中位数
if (left - l == rank)
{
return now;
}
//判断要查找的元素所在的分区,并递归查找
else if (left - l < rank)
{
return partition(nums, left + 1, r, rank - (left - l + 1));
}
else
{
return partition(nums, l, right - 1, rank);
}
}
}
Last Update 2016.11.19