Skip to content

Commit b6a1647

Browse files
committed
Runtime: 6 ms (Top 63.6%) | Memory: 2.39 MB (Top 81.8%)
1 parent ebe6167 commit b6a1647

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
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

Comments
 (0)