leecode 解题总结:324. Wiggle Sort II

#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
/*
问题:
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?

分析:给定一个为排序的数组,使其排序的形式如下:nums[0] < nums[1] > nums[2] < nums[3]
分析发现:这是一种波形的排序,中间大于两边,即: 小,大,小,大,小
如果有奇数个元素,则n/2 + 1个元素在下面,n/2个元素在上面。
如果有偶数个元素,则n/2个元素在下面,n/2个元素在上面
如果不考虑空间和时间,先从数组中挑选出n/2个最小的元素,每次挑选一个最小的元素,然后
挑选剩余元素中任意元素,重复上述操作,直至结束。
那么如何挑选最小的一半元素,可以先排序,然后进行上述操作

题目要求尽量在O(n)时间完成,并且使用原地排序。
最简单的方法:

输入:
6(数组元素个数)
1 5 1 1 6 4
6
1 3 2 2 3 1
输出:
1 4 1 5 1 6
1 2 1 3 2 3

报错:
Input:
[4,5,5,6]
Output:
[4,5,5,6]
Expected:
[5,6,4,5]

关键:
1 如果不考虑空间和时间,先排序。从数组中挑选出n/2个最小的元素,每次从最小数组中挑选一个最大的元素,然后
挑选最大数组中最大元素放入结果集,重复上述操作,直至结束。

2 摆放的时候要把较小数组中最大的元素优先放在前面,把较大数组中最大的放在前面
才能避免出现重复元素的时候不是波形。
我把较小元素从小到达排列,把较大元素从小到大排列,可能导致不是波形的排序
例如整个数组:4 5 5 6,较小数组是:4 5,较大数组为:5 6
4 5 5造成不符合要求,5 6 4符合

3参考解法:http://blog.csdn.net/qingyuanluofeng/article/details/58666552
采用三路划分+中位数方式。
通过将下标(2*i + 1) % (len|1)的方式可以构成1 3 5 0 2 4 这种下标,这种下标
刚好是奇数下标为较大数,偶数下标为较小数。
采用三路划分,将大于中位数的放在前面,中位数位置不变,小于中位数的放在后面
再加上下标映射,就可以组成

4
//获取中位数
auto mPtr = nums.begin() + size / 2;//推导类型
nth_element(nums.begin() , mPtr , nums.end());
*/


class Solution {
public:
	//进行下标映射
	int getIndex(int i , int len)
	{
		return (2*i + 1) % (len | 1);//注意这里是取余
	}

    void wiggleSort(vector<int>& nums) {
		if(nums.empty())
		{
			return;
		}
		int size = nums.size();
		//获取中位数
		auto mPtr = nums.begin() + size / 2;//推导类型
		nth_element(nums.begin() , mPtr , nums.end());
		int mid = *mPtr;
		int low = 0;
		int high = size - 1;
		int i = 0;
		//以中位数进行三路划分
		while(i <= high)
		{
			//大于中位数,交换到最左边
			if(nums[ getIndex(i , size)] > mid)
			{
				swap( nums[getIndex(i++ , size)] , nums[getIndex(low++ , size)] );
			}
			//小于中位数,交换到最右边
			else if( nums[ getIndex(i , size) ] < mid )
			{
				swap( nums[getIndex(i ,size)]  , nums[ getIndex(high--, size) ] );//注意当前位置不需要前进
			}
			//遇到中位数
			else
			{
				i++;
			}
		}

	}

    void wiggleSort2(vector<int>& nums) {
		if(nums.empty())
		{
			return;
		}
        sort(nums.begin() , nums.end());
		int size = nums.size();
		vector<int> result;
		int minBegin = 0;//
		int minEnd = (size+1)/2 - 1;
		int maxBegin = (size+1)/2;// (3+1)/2= 2 , (4+1)/2=2
		int maxEnd = size - 1;
		while(minBegin <= minEnd || maxBegin <= maxEnd)
		{
			if(minBegin <= minEnd)
			{
				result.push_back(nums.at(minEnd--));//较小数组按从大到小排列
			}
			if(maxBegin <= maxEnd)
			{
				result.push_back(nums.at(maxEnd--));//较大数组按从大到小牌类
			}
		}
		swap(nums , result);
    }
};

void print(vector<int>& result)
{
	if(result.empty())
	{
		cout << "no result" << endl;
		return;
	}
	int size = result.size();
	for(int i = 0 ; i < size ; i++)
	{
		cout << result.at(i) << " " ;
	}
	cout << endl;
}

void process()
{
	 vector<int> nums;
	 int value;
	 int num;
	 Solution solution;
	 vector<int> result;
	 while(cin >> num )
	 {
		 nums.clear();
		 for(int i = 0 ; i < num ; i++)
		 {
			 cin >> value;
			 nums.push_back(value);
		 }
		 solution.wiggleSort(nums);
		 print(nums);
	 }
}

int main(int argc , char* argv[])
{
	process();
	getchar();
	return 0;
}


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值