Given a vector of numbers, e.g.
std::vector<double> v{6.4, 5.2, 5.7, 1.8, 8.4, 8.3, 8.0, 9.1, 4.7, 7.6};
I'd like to compute a second vector of maximums of a certain window. The naive method is, of course:
std::vector<double> maximums;
unsigned int window = 3;
for (unsigned int i = window - 1; i < v.size(); i++)
{
double max = 0; // assume positive domain only
for (unsigned int j = 0; j < window; j++)
{
max = std::max(max, v[i-j]);
}
maximums.push_back(max);
}
I coded the above without testing; please forgive typos and basic errors—I'm just trying to communicate the gist of the naive method.
Is there a more efficient method?
At first I thought, "Sure, just keep a sorted list, while keeping track of an iterator pointing to the last inserted element, and remove()
that element each time you push()
a new value." But that would involve work for insertion (which I believe is O(log n)), and perhaps work for the removal, which I'm not sure about. Would that actually be more efficient than the naive method? (Certainly not more readable. I admit this would all be premature optimization and a folly to implement in my case, but I'm just curious. Imagine an array of millions of values and trying to do a rolling maximum of 1,000 at a time—in that case wouldn't a more efficient algorithm be desirable?)