The objective is to write a function that takes an array of integers and calculates for each of them the distance to the next greater value, or -1 if there isn't any.
For example, given the array, [13, 25, 10, 5, 8, 2, 20]
, the return value would be [1, -1, 4, 1, 2, 1, -1]
. Working our way from left to right, the next number greater than 13 is 1 hop away, there is no number greater than 25, the next number greater than 10 is 4 hops away, and so on. Note that this necessarily means the last value in the result is -1 since there is no next number that is greater.
It might be tempting at first glance to traverse the array from left to right, checking each following value against the current one, but that would lead to a solution with an O(n2) worst case runtime. To do better we make use of information we generate as we traverse through the array backwards. Instead of incrementing our counter by one each time as we search for the next greater value, we can check the corresponding value in the result array and see how many hops to a value that exceeds it. We can then hop to that value directly and check again. If we reach a -1 along the way we can stop, since this indicates there is no greater value ahead.
This solution saves us hops since we don't repeat unnecessary traversals. In fact, in the worst case—an ever decreasing set of values—we only perform one check for each value, leading to linear runtime.
The visualization here shows randomly chosen array values on a line chart. The solid red dot is the one for which we're calculating an output value. The red circle is the value being compared. Notice how the circle hops around and stops after very few hops—often after only one.
https://d3js.org/d3.v3.min.js