LeetCode:324. Wiggle Sort II
题目描述
Given an unsorted array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]…
Example 1:
Input: nums = [1, 5, 1, 1, 6, 4]
Output: One possible answer is [1, 4, 1, 5, 1, 6].
Example 2:
Input: nums = [1, 3, 2, 2, 3, 1]
Output: 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?
解题思路
- 找到中位数
- 把所有的中位数向中间靠拢
- 中位数左右两边各自旋转(尽量别让中位数相遇)
- 中位数左边的在偶数位(第
0
位是偶数位),中位数右边的在奇数位
AC 代码
// 通过 partition 找到第 k 个元素(从 0 开始)
func partition(nums []int, k int) {
if len(nums) <= k || (len(nums) == 1 && k == 0 ) {
return
}
i, j := 0, len(nums)-1
for i < j {
for i <= j && nums[i] <= nums[0] { i++ }
for i <= j && nums[j] > nums[0] { j-- }
if i < j {
nums[i], nums[j] = nums[j], nums[i]
}
}
nums[0], nums[j] = nums[j], nums[0]
if j > k {
partition(nums[0:j], k)
} else if j < k {
partition(nums[j+1:], k-(j+1))
}
}
func middle(nums []int) {
mid := (len(nums)-1)/2
i, j := 0, mid-1
for i < j {
for i < j && nums[i] != nums[mid] { i++ }
for i < j && nums[j] == nums[mid] { j-- }
if i < j {
nums[i], nums[j] = nums[j], nums[i]
}
}
i, j = mid+1, len(nums)-1
for i < j {
for i < j && nums[i] == nums[mid] { i++ }
for i < j && nums[j] != nums[mid] { j-- }
if i < j {
nums[i], nums[j] = nums[j], nums[i]
}
}
}
// [beg, end]
func reverse(nums []int, beg int, end int) {
for beg <= end {
nums[beg], nums[end] = nums[end], nums[beg]
beg++
end--
}
}
func wiggleSort(nums []int) {
oddPos := len(nums)/2
// 1. 找到中位数
partition(nums, (len(nums)-1)/2)
// 2. 中位数居中
middle(nums)
// 3. 左右各自翻转(尽量别让中位数相遇)
reverse(nums, 0, len(nums)-oddPos-1)
reverse(nums, len(nums)-oddPos, len(nums)-1)
// 4. 中位数以前的在偶数位,中位数之后的在奇数位
right := len(nums)-oddPos
// 4 3 2 1 8 7 6 5 ==> 4 8 3 7 2 6 1 5
temp := []int{}
for i := 0; i < len(nums); i++ {
temp = append(temp, nums[i])
}
for i := 0; i < len(nums); i++ {
if i % 2 == 0 {
nums[i] = temp[i/2]
} else {
nums[i] = temp[right+i/2]
}
}
}