[LintCode] Wiggle Sort II 扭动排序之二
Given an unsorted array nums, reorder it such that
nums[0] < nums[1] > nums[2] < nums[3]....
Notice
You may assume all input has valid answer.
Example
Given nums = [1, 5, 1, 1, 6, 4], one possible answer is [1, 4, 1, 5, 1, 6].
Given nums = [1, 3, 2, 2, 3, 1], one possible answer is [2, 3, 1, 3, 1, 2].
Challenge
Can you do it in O(n) time and/or in-place with O(1) extra space?
LeetCode上的原题,请参见我之前的博客Wiggle Sort II。
解法一:
class Solution { public: /** * @param nums a list of integer * @return void */ void wiggleSort(vector<int>& nums) { vector<int> t = nums; int n = nums.size(), k = (n + 1) / 2, j = n; sort(t.begin(), t.end()); for (int i = 0; i < n; ++i) { nums[i] = i & 1 ? t[--j] : t[--k]; } } };
解法二:
class Solution { public: /** * @param nums a list of integer * @return void */ void wiggleSort(vector<int>& nums) { #define A(i) nums[(1 + i * 2) % (n | 1)] int n = nums.size(), i = 0, j = 0, k = n - 1; auto midptr = nums.begin() + n / 2; nth_element(nums.begin(), midptr, nums.end()); int mid = *midptr; while (j <= k) { if (A(j) > mid) swap(A(i++), A(j++)); else if (A(j) < mid) swap(A(j), A(k--)); else ++j; } } };
解法三:
class Solution { public: /** * @param nums a list of integer * @return void */ void wiggleSort(vector<int>& nums) { #define A(i) nums[(1 + i * 2) % (n | 1)] int n = nums.size(), i = 0, j = 0, k = n - 1; int mid = partition(nums, 0, n - 1, n / 2); while (j <= k) { if (A(j) > mid) swap(A(i++), A(j++)); else if (A(j) < mid) swap(A(j), A(k--)); else ++j; } } int partition(vector<int> nums, int l, int r, int rank) { int left = l, right = r, pivot = nums[left]; while (left < right) { while (left < right && nums[right] >= pivot) --right; nums[left] = nums[right]; while (left < right && nums[left] <= pivot) ++left; nums[right] = nums[left]; } if (left - l == rank) return pivot; else if (left - l < rank) return partition(nums, left + 1, r, rank - (left - l + 1)); else return partition(nums, l, right - 1, rank); } };