Skip to content

Commit 118d17a

Browse files
authored
Merge pull request #74 from marttp/rust-sliding-windows
Rust Chapter 5: Sliding Windows
2 parents bf2407c + f75eb21 commit 118d17a

4 files changed

+126
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
fn longest_substring_with_unique_chars(s: String) -> i32 {
2+
use std::collections::HashSet;
3+
4+
let mut max_len = 0;
5+
let mut hash_set = HashSet::new();
6+
let mut left = 0;
7+
let mut right = 0;
8+
let s = s.as_bytes();
9+
10+
while right < s.len() {
11+
// If we encounter a duplicate character in the window, shrink
12+
// the window until it's no longer a duplicate.
13+
while hash_set.contains(&s[right]) {
14+
hash_set.remove(&s[left]);
15+
left += 1;
16+
}
17+
// Once there are no more duplicates in the window, update
18+
// 'max_len' if the current window is larger.
19+
max_len = max_len.max(right - left + 1);
20+
hash_set.insert(s[right]);
21+
// Expand the window.
22+
right += 1;
23+
}
24+
25+
max_len as i32
26+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
fn longest_substring_with_unique_chars_optimized(s: String) -> i32 {
2+
use std::collections::HashMap;
3+
4+
let mut max_len = 0;
5+
let mut prev_indexes = HashMap::new();
6+
let mut left = 0;
7+
let mut right = 0;
8+
// Shadowing 's' by converting it to a byte array/slice.
9+
let s = s.as_bytes();
10+
11+
while right < s.len() {
12+
// If a previous index of the current character is present
13+
// in the current window, it's a duplicate character in the
14+
// window.
15+
if let Some(&prev_index) = prev_indexes.get(&s[right]) {
16+
// Shrink the window to exclude the previous occurrence
17+
// of this character.
18+
if prev_index >= left {
19+
left = prev_index + 1;
20+
}
21+
}
22+
// Update 'max_len' if the current window is larger.
23+
max_len = max_len.max(right - left + 1);
24+
prev_indexes.insert(s[right], right);
25+
// Expand the window.
26+
right += 1;
27+
}
28+
29+
max_len as i32
30+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
fn longest_uniform_substring_after_replacements(s: String, k: i32) -> i32 {
2+
use std::collections::HashMap;
3+
4+
let mut freqs = HashMap::new();
5+
let mut highest_freq = 0;
6+
let mut max_len = 0;
7+
let mut left = 0;
8+
let mut right = 0;
9+
let s = s.as_bytes();
10+
11+
while right < s.len() {
12+
// Update the frequency of the character at the right pointer
13+
// and the highest frequency for the current window.
14+
*freqs.entry(s[right]).or_insert(0) += 1;
15+
highest_freq = highest_freq.max(*freqs.get(&s[right]).unwrap());
16+
// Calculate replacements needed for the current window.
17+
let num_chars_to_replace = ((right - left + 1) as i32) - highest_freq;
18+
// Slide the window if the number of replacements needed exceeds
19+
// 'k'. The right pointer always gets advanced, so we just need
20+
// to advance 'left'.
21+
if num_chars_to_replace > k {
22+
// Remove the character at the left pointer from the hash map
23+
// before advancing the left pointer.
24+
*freqs.get_mut(&s[left]).unwrap() -= 1;
25+
left += 1;
26+
}
27+
// Since the length of the current window increases or stays the
28+
// same, assign the length of the current window to 'max_len'.
29+
max_len = max_len.max(right - left + 1);
30+
// Expand the window.
31+
right += 1;
32+
}
33+
34+
max_len as i32
35+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
fn substring_anagrams(s: String, t: String) -> i32 {
2+
let len_s = s.len();
3+
let len_t = t.len();
4+
if len_t > len_s {
5+
return 0;
6+
}
7+
let mut count = 0;
8+
let mut expected_freqs = vec![0; 26];
9+
let mut window_freqs = vec![0; 26];
10+
// Populate 'expected_freqs' with the characters in string 't'.
11+
for c in t.bytes() {
12+
expected_freqs[(c - b'a') as usize] += 1;
13+
}
14+
let mut left = 0;
15+
let mut right = 0;
16+
while right < len_s {
17+
// Add the character at the right pointer to 'window_freqs'
18+
// before sliding the window.
19+
window_freqs[(s.as_bytes()[right] - b'a') as usize] += 1;
20+
// If the window has reached the expected fixed length, we
21+
// advance the left pointer as well as the right pointer to
22+
// slide the window.
23+
if right - left + 1 == len_t {
24+
if window_freqs == expected_freqs {
25+
count += 1;
26+
}
27+
// Remove the character at the left pointer from
28+
// 'window_freqs' before advancing the left pointer.
29+
window_freqs[(s.as_bytes()[left] - b'a') as usize] -= 1;
30+
left += 1;
31+
}
32+
right += 1;
33+
}
34+
count
35+
}

0 commit comments

Comments
 (0)