Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Given an array, can I find in O(n) the longest range, whose endpoints are the greatest values in the range?

For a given array of integers, find the maximum distance between 2 points (i and j) that have higher values ​​than any element between them.

Example:

 values: 0 10  8  9  6  7  4 10  0 index : 0  1  2  3  4  5  6  7  8  

for the values above the solution is i=1, j=7, but

  • if the value of index 7 is 9 instead of 10 the solution is i=3, j=7
  • if the value of index 7 is 7 instead of 10 the solution is i=5, j=7

I can't see a solution in O(n) ... anyone ?

like image 957
cprogrammer Avatar asked Mar 23 '11 08:03

cprogrammer


People also ask

What is the range of an array?

The range of an array is the difference between the maximum element of the array and the minimum element. You want to find the minimum range of the array by doing any number of operations on the array. You can do multiple operations on a single element as well.

What is the maximum index of the array?

max index(es) is the index for the first max value. If array is multidimensional, max index(es) is an array whose elements are the indexes for the first maximum value in array. min value is of the same data type and structure as the elements in array. min index(es) is the index for the first min value.

Which method in JS return a range of elements of an array?

The slice() method returns selected elements in an array, as a new array.


1 Answers

A simple stack based solution. Iterate over the array left to right, with the stack holding elements (technically, indexes, but use values for comparisons) that are either:

  1. The largest from the left (i.e. no larger or equal element between the start of the array and the element)
  2. The largest since the previous element on the stack.

When processing the next element x, pop elements smaller than x as long as they are from the category 2. above, then push x on the stack. Obviously you need to keep the current max to be able to discern between category 2 and 1 in constant time.

The processing above is O(n) - each element can be pushed at most once and popped at most once. Having the final stack, just check neighboring pairs (on the stack) - one of the pairs is the solution. This too is O(n).

Here's a picture with what should stay on the stack (the fat rectangles) after the whole scan of the array:

Stack-bars

(There's a small mistake in the above picture: fourth bar from the left should either be thick or drawn shorter than the first one, sorry)

Why this works: the final stack contains all elements of the input array that are not between any two larger elements (I've skipped the case of an element between two equal elements) . The solution is obviously a neighboring pair of such elements.

Here's an implementation in Python:

from collections import namedtuple  E = namedtuple('E', 'i x')  def maxrange(iterable):     stack = [E(0, None)]*2 # push sentinel values     maxsofar = None      top = lambda: stack[-1] # peek at the top element on the stack      for i, x in enumerate(iterable):         while top().x < x and top().x < maxsofar:             stack.pop()         stack.append(E(i, x)) # push         maxsofar = max(maxsofar, x)      return max(b.i-a.i for a,b in zip(stack, stack[1:])) 

Example:

>>> maxrange([2,1,3]) 2 
like image 195
Rafał Dowgird Avatar answered Oct 11 '22 23:10

Rafał Dowgird