shole
shole

Reputation: 4094

Moving window RMQ performance improvement

Say I have an array of integers A of length N, also I have an integer L <= N.

What I am trying to find is the minimum of the range [0, L-1], [1,L], [2,L+1]....[N-L,N-1]

(like a moving window of length L from left to right)


My algorithm now is O(N lg N) with O(N lg N) preprocess:

  1. Save all numbers A[0...L-1] in a multi-set S, also store the number in a queue Q in order. The minimum of [0, L-1] is simply the first element of S. O(N lg N)
  2. Pop out the first element of Q, find this element in S and delete it. Then push A[L] in S. The minimum of [1, L] is simply the first element of S. O(lg N)
  3. Repeat step 2 for all possible range, move to next element each iteration. O(N)

Total is O(N lg N).


I wonder if there is any algorithm which can achieve better than this with following requirements:

  1. Preprocess time (If needed) is O(N)
  2. Query time if O(1)

I have done some research on RMQ, the nearest method I found is using sparse table which achieve O(1) query time but O(N lg N) preprocess time. Another method which reduce RMQ to LCA problem can meet the requirements but it needs some restriction on the array A.

So is it possible that, with no restriction on A, the requirements can be fulfilled when solving my problem?

Upvotes: 1

Views: 158

Answers (1)

IVlad
IVlad

Reputation: 43477

Yes, use a deque. We will keep the elements sorted ascendingly, so the first element is always the minimum in [i - L + 1, i], for the current position i. We won't keep actual elements, but their positions.

d = empty deque
for i = 0 to n-1:

    // get rid of too old elements
    while !d.empty && i - d.front + 1 > L:
        d.pop_front()

    // keep the deque sorted
    while !d.empty && A[d.back] > A[i]        
        d.pop_back()

    d.push_back(i)
    // A[d.front] is the minimum in `[i - L + 1, i]

Since every element enters and leaves the deque at most once, this is O(n).

Upvotes: 3

Related Questions