Find max values of all subarrays of specific length This is one of the coding questions that I subscribe to and I wanted to solve it in Rust. I would really appreciate your feedback for improving this code and writing idiomatic Rust.


  Given an array of integers and a number k, where 1 &lt;= k &lt;= length of the array, compute the maximum values of each subarray of length k.
  
  For example, given array = [10, 5, 2, 7, 8, 7] and k = 3, we should
  get: [10, 7, 8, 8], since:

10 = max(10, 5, 2)
7 = max(5, 2, 7)
8 = max(2, 7, 8)
8 = max(7, 8, 7)

  
  Do this in \$O(n)\$ time and \$O(k)\$ space. You can modify the input array
  in-place and you do not need to store the results. You can simply
  print them out as you compute them.


This is my first attempt:
https://gist.github.com/ginghamtaus/236e8a1d75237a47769ca74b23ac45ac

This is my second attempt:
https://gist.github.com/ginghamtaus/6e0003e43e020130c8fd9346c9019522

use std::collections::VecDeque;

fn main() {
    let a = [10, 5, 2, 7, 8, 7];
    let k = 3;
    let mut deque: VecDeque&lt;usize&gt; = VecDeque::new();
    for i in 0..a.len() {
        match deque.front() {
            None =&gt; deque.push_back(i),
            Some(_) =&gt; {
                let mut done = false;
                while !done {
                    match deque.back() {
                        Some(&amp;x) =&gt; {
                            if a[i] &gt; a[x] {
                                deque.pop_back();
                            }
                            else {
                                done = true;
                            }
                        },
                        _ =&gt; { done = true; }
                    }
                }
                deque.push_back(i); 
            }
        }

        if i + 1 &gt;= k  {
            match deque.front() {
                Some(&amp;x) =&gt; {
                    println!("max({:?}) = {}", &amp;a[i+1-k..i+1], a[x]);
                    if x &lt;= (i + 1 - k) {
                        deque.pop_front();
                    }
                },
                _ =&gt; ()
            };
        }
    }
}
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.