In an unsorted array, replace every element by the first larger element to the right

前端 未结 2 1937
攒了一身酷
攒了一身酷 2020-12-28 20:39

In an unsorted array, we have to replace every element by the first element to the right that is larger than the current element. If none of the elements to the right are b

2条回答
  •  青春惊慌失措
    2020-12-28 21:05

    The main idea is to process the array in reverse order (from right to left). We make a few observations:

    • If we are currently processing index i, k > j > i and A[k] ≤ A[j], then we call element k irrelevant, because it will never be the result for any of the elements 1, 2, ..., k
    • The relevant elements right of an index i therefore form a monotonically strictly increasing subsequence of A[i+1..n-1].

    In your example, the sequences of relevant elements would be from right to left:

           []    
          [8]
        [4,8]
          [9]
        [5,9]
      [2,5,9]
      [1,5,9]
    

    It looks like a stack, and we can indeed use a stack to maintain this sequence between iterations.

    When processing a new element, we first need to find the result for the array element. The observation is that the result is the topmost element on the stack that is not invalidated by the new element. Therefore we can just pop from the stack all elements that have become irrelevant. What is then on the top is our result. We can then push the new element because it is relevant by our definition.

    stack = []
    A = [3, 1, 2, 5, 9, 4, 8]
    result = [-1]*len(A)
    for i := len(A) - 1 to 0:
        # remove all elements made irrelevant by A[i]
        while not stack.empty() && stack.top() <= A[i]:
            stack.pop()
        # now the top of the stack is the result for index i
        if not stack.empty():
            R[i] = stack.top()
        # push the new element on the stack. The stack will still contain all relevant 
        # elements in increasing order from top to bottom
        stack.push(A[i])
    

    The loop invariant for iteration i is "stack contains the subsequence of relevant elements to the right of index i". It is easy to verify and implies the correctness of this algorithm.

    Every element is pushed and popped at most once, so we have a total runtime of Ο(n).

提交回复
热议问题