Find max values of all subarrays of specific length
Run rustfmt. It will automatically tell you such things as:


else blocks in Rust belong on the same line as the closing } and opening { 
spaces belong around binary arithmetic operators: &amp;a[i + 1 - k..i + 1].

Run clippy. It will automatically tell you such things as:


You are using match for a single pattern. Use if let instead.

Don't specify types of variables if type inference can handle it.
If you don't care about the value of an Option, use is_some / is_none instead of matching on it.
Both branches end with push_back, that shared logic should be pulled out of the conditional.
If all you care about is if the front of the queue is present, all you really care about is if it is empty.
You can continue to simplify by transofrming that into a while let and using break.
I'd create a function (or an Iterator implementation) to separate the algorithm and the driver.




use std::collections::VecDeque;

fn max_of_subarrays&lt;F&gt;(a: &amp;[i32], k: usize, f: F)
where
    F: Fn(&amp;[i32], i32),
{
    let mut deque = VecDeque::new();

    for i in 0..a.len() {
        while let Some(&amp;x) = deque.back() {
            if a[i] &gt; a[x] {
                deque.pop_back();
            } else {
                break;
            }
        }

        deque.push_back(i);

        if i + 1 &gt;= k {
            if let Some(&amp;x) = deque.front() {
                f(&amp;a[i + 1 - k..i + 1], a[x]);
                if x &lt;= (i + 1 - k) {
                    deque.pop_front();
                }
            }
        }
    }
}

fn main() {
    let a = [10, 5, 2, 7, 8, 7];
    let k = 3;

    max_of_subarrays(&amp;a, k, |sub, max| {
        println!("max({:?}) = {}", sub, max);
    });
}




Truthfully, I wouldn't do any of that unless I had a really good reason. Instead, I'd just use the less efficient algorithm but very concise implementation:

fn main() {
    let a = [10, 5, 2, 7, 8, 7];
    let k = 3;

    for (sub, max) in a.windows(k).flat_map(|sub| sub.iter().max().map(|max| (sub, max))) {
        println!("max({:?}) = {}", sub, max);
    }
}


I didn't take the time to benchmark this, but there's no allocation required here, so I'd expect it to be faster than the better algorithm in certain cases.