Skip to content

Commit 18b18cb

Browse files
authored
Merge pull request #174 from ia7ck/sliding-window
sliding-window minimum/maximum
2 parents cc46c85 + fee90cd commit 18b18cb

File tree

1 file changed

+50
-53
lines changed

1 file changed

+50
-53
lines changed

algo/sliding_window/src/lib.rs

Lines changed: 50 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use std::cmp::Ordering::{Greater, Less};
21
use std::collections::VecDeque;
32

43
/// 幅 `window_width` の区間すべてに対し最小値を求めます。
@@ -27,55 +26,53 @@ use std::collections::VecDeque;
2726
/// assert_eq!(
2827
/// minimums,
2928
/// vec![
30-
/// 4, // 4 7 7 8 5 7
31-
/// 5, // 7 7 8 5 7 6
32-
/// 5, // 7 8 5 7 6 9
33-
/// 5, // 8 5 7 6 9 9
34-
/// 2, // 5 7 6 9 9 2
35-
/// 2, // 7 6 9 9 2 8
36-
/// 2, // 6 9 9 2 8 3
29+
/// &4, // 4 7 7 8 5 7
30+
/// &5, // 7 7 8 5 7 6
31+
/// &5, // 7 8 5 7 6 9
32+
/// &5, // 8 5 7 6 9 9
33+
/// &2, // 5 7 6 9 9 2
34+
/// &2, // 7 6 9 9 2 8
35+
/// &2, // 6 9 9 2 8 3
3736
/// ]
3837
/// );
3938
/// ```
40-
pub fn sliding_window_minimum<T>(a: &[T], window_width: usize) -> Vec<T>
39+
pub fn sliding_window_minimum<T>(a: &[T], window_width: usize) -> Vec<&T>
4140
where
42-
T: Ord + Clone,
41+
T: Ord,
4342
{
44-
sliding_window(a, window_width, true)
43+
sliding_window(a, window_width, |last, new| last >= new)
4544
}
4645

4746
/// [`sliding_window_minimum`](fn.sliding_window_minimum.html) の最大値バージョンです。
48-
pub fn sliding_window_maximum<T>(a: &[T], window_width: usize) -> Vec<T>
47+
pub fn sliding_window_maximum<T>(a: &[T], window_width: usize) -> Vec<&T>
4948
where
50-
T: Ord + Clone,
49+
T: Ord,
5150
{
52-
sliding_window(a, window_width, false)
51+
sliding_window(a, window_width, |last, new| last <= new)
5352
}
5453

55-
fn sliding_window<T>(a: &[T], window_width: usize, choose_minimum: bool) -> Vec<T>
54+
fn sliding_window<T, F>(a: &[T], window_width: usize, pop_back_cond: F) -> Vec<&T>
5655
where
57-
T: Ord + Clone,
56+
T: Ord,
57+
F: Fn(&T, &T) -> bool, // (last, new)
5858
{
5959
assert!(0 < window_width && window_width <= a.len());
6060
let mut result = Vec::new();
61-
let mut arg_min_max_candidates: VecDeque<usize> = VecDeque::new();
61+
let mut positions: VecDeque<usize> = VecDeque::new();
6262
for (i, v) in a.iter().enumerate() {
63-
while !arg_min_max_candidates.is_empty() {
64-
let back = arg_min_max_candidates.back().unwrap();
65-
if choose_minimum && a[*back].cmp(v) == Less {
63+
while let Some(last) = positions.back().copied() {
64+
if pop_back_cond(&a[last], v) {
65+
positions.pop_back();
66+
} else {
6667
break;
6768
}
68-
if !choose_minimum && a[*back].cmp(v) == Greater {
69-
break;
70-
}
71-
arg_min_max_candidates.pop_back();
7269
}
73-
arg_min_max_candidates.push_back(i);
70+
positions.push_back(i);
7471
if i >= window_width - 1 {
75-
let arg_min_max = arg_min_max_candidates.front().unwrap();
76-
result.push(Clone::clone(&a[*arg_min_max]));
77-
if *arg_min_max == i - (window_width - 1) {
78-
arg_min_max_candidates.pop_front();
72+
let p = positions.front().copied().unwrap();
73+
result.push(&a[p]);
74+
if p == i - (window_width - 1) {
75+
positions.pop_front();
7976
}
8077
}
8178
}
@@ -92,23 +89,23 @@ mod tests {
9289
assert_eq!(
9390
sliding_window_minimum(&a, 4),
9491
vec![
95-
2, // 2 2 3 6
96-
0, // 2 3 6 0
97-
0, // 3 6 0 6
98-
0, // 6 0 6 7
99-
0, // 0 6 7 9
100-
6, // 6 7 9 7
101-
7, // 7 9 7 7
102-
4, // 9 7 7 4
103-
4 // 7 7 4 9
92+
&2, // 2 2 3 6
93+
&0, // 2 3 6 0
94+
&0, // 3 6 0 6
95+
&0, // 6 0 6 7
96+
&0, // 0 6 7 9
97+
&6, // 6 7 9 7
98+
&7, // 7 9 7 7
99+
&4, // 9 7 7 4
100+
&4, // 7 7 4 9
104101
]
105102
);
106103

107-
assert_eq!(sliding_window_minimum(&a, 1), a);
104+
assert_eq!(sliding_window_minimum(&a, 1), a.iter().collect::<Vec<_>>());
108105

109106
assert_eq!(
110107
sliding_window_minimum(&a, a.len()),
111-
vec![a.iter().copied().min().unwrap()],
108+
vec![a.iter().min().unwrap()],
112109
);
113110
}
114111

@@ -118,35 +115,35 @@ mod tests {
118115
assert_eq!(
119116
sliding_window_maximum(&a, 4),
120117
vec![
121-
6, // 2 2 3 6
122-
6, // 2 3 6 0
123-
6, // 3 6 0 6
124-
7, // 6 0 6 7
125-
9, // 0 6 7 9
126-
9, // 6 7 9 7
127-
9, // 7 9 7 7
128-
9, // 9 7 7 4
129-
9 // 7 7 4 9
118+
&6, // 2 2 3 6
119+
&6, // 2 3 6 0
120+
&6, // 3 6 0 6
121+
&7, // 6 0 6 7
122+
&9, // 0 6 7 9
123+
&9, // 6 7 9 7
124+
&9, // 7 9 7 7
125+
&9, // 9 7 7 4
126+
&9, // 7 7 4 9
130127
]
131128
);
132129

133-
assert_eq!(sliding_window_maximum(&a, 1), a);
130+
assert_eq!(sliding_window_maximum(&a, 1), a.iter().collect::<Vec<_>>());
134131

135132
assert_eq!(
136133
sliding_window_maximum(&a, a.len()),
137-
vec![a.iter().copied().max().unwrap()],
134+
vec![a.iter().max().unwrap()],
138135
);
139136
}
140137

141138
#[test]
142139
#[should_panic]
143140
fn test_empty_0() {
144-
assert_eq!(sliding_window_minimum::<u32>(&[], 0), vec![]);
141+
assert!(sliding_window_minimum::<u32>(&[], 0).is_empty());
145142
}
146143

147144
#[test]
148145
#[should_panic]
149146
fn test_empty_1() {
150-
assert_eq!(sliding_window_minimum::<u32>(&[], 1), vec![]);
147+
assert!(sliding_window_minimum::<u32>(&[], 1).is_empty());
151148
}
152149
}

0 commit comments

Comments
 (0)