1
+ // Runtime: 6 ms (Top 63.6%) | Memory: 2.39 MB (Top 81.8%)
2
+
3
+ use std:: cmp:: Ordering :: { Less , Equal , Greater } ;
4
+
5
+ impl Solution {
6
+ pub fn wiggle_sort ( nums : & mut Vec < i32 > ) {
7
+ if Self :: wiggle_forward ( & mut nums[ ..] ) {
8
+ return ;
9
+ }
10
+ if Self :: wiggle_backward ( & mut nums[ ..] ) {
11
+ return ;
12
+ }
13
+ let pivot = nums[ 0 ] ;
14
+ if Self :: wiggle_pivot ( & mut nums[ ..] , pivot) {
15
+ return ;
16
+ }
17
+ panic ! ( "not wiggle-sortable" ) ;
18
+ }
19
+ fn wiggle_forward ( nums : & mut [ i32 ] ) -> bool {
20
+ let mut i = 0 ;
21
+ let mut j = 0 ;
22
+ while j < nums. len ( ) {
23
+ // INVARIANTS:
24
+ // (0) 0 <= i <= j <= nums.len, i < nums.len
25
+ // (1) nums[..i+1] is wiggle-sorted
26
+ // (2) nums[i..j] are all identical
27
+ // (3) nums[j..] are unchanged since the start of the loop
28
+ if j <= i {
29
+ j = i + 1 ;
30
+ continue ;
31
+ }
32
+ match ( i % 2 == 0 , i32:: cmp ( & nums[ j] , & nums[ i] ) ) {
33
+ ( true , Greater ) | ( false , Less ) => {
34
+ if j <= i + 1 {
35
+ i += 1 ;
36
+ } else {
37
+ nums. swap ( j, i + 1 ) ;
38
+ i += 2 ;
39
+ j += 1 ;
40
+ }
41
+ } ,
42
+ ( true , Less ) | ( false , Greater ) => {
43
+ nums. swap ( j, i) ;
44
+ i += 1 ;
45
+ j += 1 ;
46
+ } ,
47
+ ( _, Equal ) => j += 1 ,
48
+ }
49
+ }
50
+ return i >= nums. len ( ) - 1 ;
51
+ }
52
+ fn wiggle_backward ( nums : & mut [ i32 ] ) -> bool {
53
+ let mut i = nums. len ( ) ;
54
+ let mut j = nums. len ( ) ;
55
+ while j > 0 {
56
+ // INVARIANTS HERE:
57
+ // (0) 0 <= j <= i <= nums.len and 0 < i
58
+ // (1) nums[i-1..] is wiggle-sorted
59
+ // (2) nums[j..i] are all identical
60
+ // (3) nums[..j] are unchanged since the start of the loop
61
+ if j >= i {
62
+ j = i - 1 ;
63
+ continue ;
64
+ }
65
+ match ( i % 2 == 0 , i32:: cmp ( & nums[ j-1 ] , & nums[ i-1 ] ) ) {
66
+ ( true , Less ) | ( false , Greater ) => {
67
+ if j >= i - 1 {
68
+ i -= 1 ;
69
+ } else {
70
+ nums. swap ( j - 1 , i - 2 ) ;
71
+ i -= 2 ;
72
+ j -= 1 ;
73
+ }
74
+ } ,
75
+ ( true , Greater ) | ( false , Less ) => {
76
+ nums. swap ( j - 1 , i - 1 ) ;
77
+ i -= 1 ;
78
+ j -= 1 ;
79
+ } ,
80
+ ( _, Equal ) => j -= 1 ,
81
+ }
82
+ }
83
+ return i <= 1 ;
84
+ }
85
+ fn wiggle_pivot ( nums : & mut [ i32 ] , pivot : i32 ) -> bool {
86
+ let n = nums. len ( ) ;
87
+ let m = ( n + 1 ) / 2 ;
88
+ let index = move |i : usize | if i < m {
89
+ 2 * ( m - i - 1 )
90
+ } else {
91
+ 2 * ( n - i) - 1
92
+ } ;
93
+ let mut min_i = 0 ;
94
+ let mut max_i = n;
95
+ let mut i = 0 ;
96
+ while i < max_i {
97
+ match nums[ index ( i) ] . cmp ( & pivot) {
98
+ Less => {
99
+ nums. swap ( index ( i) , index ( min_i) ) ;
100
+ i += 1 ;
101
+ min_i += 1 ;
102
+ } ,
103
+ Equal => {
104
+ i += 1 ;
105
+ } ,
106
+ Greater => {
107
+ nums. swap ( index ( i) , index ( max_i - 1 ) ) ;
108
+ max_i -= 1 ;
109
+ } ,
110
+ }
111
+ }
112
+ return min_i <= m && max_i >= m;
113
+ }
114
+ }
0 commit comments