-
Notifications
You must be signed in to change notification settings - Fork 22
/
Copy path324.wiggle-sort-ii.py
102 lines (87 loc) · 2.61 KB
/
324.wiggle-sort-ii.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# Tag: Array, Divide and Conquer, Greedy, Sorting, Quickselect
# Time: -
# Space: -
# Ref: -
# Note: -
# Given an integer array nums, reorder it such that nums[0] < nums[1] > nums[2] < nums[3]....
# You may assume the input array always has a valid answer.
#
# Example 1:
#
# Input: nums = [1,5,1,1,6,4]
# Output: [1,6,1,5,1,4]
# Explanation: [1,4,1,5,1,6] is also accepted.
#
# Example 2:
#
# Input: nums = [1,3,2,2,3,1]
# Output: [2,3,1,3,1,2]
#
#
# Constraints:
#
# 1 <= nums.length <= 5 * 104
# 0 <= nums[i] <= 5000
# It is guaranteed that there will be an answer for the given input nums.
#
#
# Follow Up: Can you do it in O(n) time and/or in-place with O(1) extra space?
class Solution:
def wiggleSort(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
arr = sorted(nums)
for i in range(1, n, 2):
nums[i] = arr.pop()
for i in range(0, n, 2):
nums[i] = arr.pop()
# follow up
class Solution:
def wiggleSort(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
left = 0
right = n - 1
medean = self.quick_select(nums, right // 2)
def virtual(i:int):
return (1 + 2 * i) % (n | 1)
i = 0
while i <= right:
if nums[virtual(i)] > medean:
nums[virtual(i)], nums[virtual(left)] = nums[virtual(left)], nums[virtual(i)]
i += 1
left += 1
elif nums[virtual(i)] < medean:
nums[virtual(i)], nums[virtual(right)] = nums[virtual(right)], nums[virtual(i)]
right -= 1
else:
i += 1
def quick_select(self, nums: list, k: int) -> int:
left = 0
right = len(nums) - 1
while left < right:
pick = self.partition(nums, left, right)
if pick == k:
break
if pick < k:
left = pick + 1
else:
right = pick - 1
return nums[k]
def partition(self, nums:list, left: int, right: int) -> int:
pivot = nums[right]
l = left
r = right - 1
while l <= r:
if nums[l] > pivot and nums[r] < pivot:
nums[l], nums[r] = nums[r], nums[l]
if nums[l] <= pivot:
l += 1
if nums[r] >= pivot:
r -= 1
nums[l], nums[right] = nums[right], nums[l]
return l