在未排序的数组中,将第一个较大的元素替换为右边的每个元素

时间:2014-03-06 18:33:13

标签: arrays algorithm data-structures time-complexity

在未排序的数组中,我们必须用右边的第一个元素替换每个元素,这个元素大于当前元素。如果右边的元素都不大,则应该用-1替换。

示例:

3  1  2  5  9  4  8   should be converted to
5  2  5  9 -1  8 -1

我可以想到一个简单的解决方案,我们用整个数组检查每个元素,这是一个Ο(n²)解决方案。有更好的方法吗?

2 个答案:

答案 0 :(得分:11)

主要思想是以相反的顺序(从右到左)处理数组。我们做了一些观察:

  • 如果我们当前正在处理索引 i k> j>我A[k] ≤ A[j],然后我们将元素 k 称为无关,因为它永远不会是任何元素 1,2,...,k的结果
  • 索引 i 的相关元素权利因此形成A[i+1..n-1]的单调严格增加的子序列。

在您的示例中,相关元素的序列将从右到左:

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

它看起来像一个堆栈,我们确实可以使用堆栈来在迭代之间维护这个序列。

处理新元素时,我们首先需要找到数组元素的结果。观察结果是结果是堆栈中最新元素由新元素无效。因此,我们可以从堆栈中弹出所有已变得无关紧要的元素。那么最重要的是我们的结果。然后我们可以推送新元素,因为它与我们的定义相关。

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])

迭代i的循环不变量是“ stack包含索引i ”右侧相关元素的子序列。它很容易验证并暗示了该算法的正确性。

每个元素最多被推送和弹出一次,因此我们的总运行时间为Ο(n)

答案 1 :(得分:3)

您可以使用堆叠,时间复杂度为 O(N)

<强> algo: 从左侧开始向右移动。当你从数组中挑选一个元素时(比方说x)弹出堆栈直到堆栈中的元素(比方说y)具有大于数组元素的元素,即x>年。比推动元素即x叠加。

e.g。 {40,50,11,32,55,68,75}。这里s是堆栈。

40,因为s是空的推它。 s: 40

50,如s.peek()&lt;如此流行40(40的元素大于50)比推50。s: 50

  

下一个更高的元素40 - 50。

11,s.peek()&gt; 11所以推11. [{1}}

32,s.peek()&lt; 32,所以弹出元素,现在它是50,大于32因此推32.。s: 50, 11

  

下一个更高的元素11 - 32。

55,s.peek()&lt; 55,所以弹出元素,即32然后弹出下一个以及50&lt; 55,而不是推55. s: 50 ,32

  

下一个更高的元素是32 - 55。

     

下一个更高的元素50 - 55。

68,s.peek()&lt; 68所以弹出它并推动68. s: 55

75,s.peek()&lt; 75弹出它然后推75 s: 68

  

下一个更高的元素68 - 75。

由于数组没有任何元素,因此不会弹出堆栈,表示数组中的所有元素都没有更大的元素,即-1。

  

下一个更高的元素是75 - -1。

代码中的算法相同:

s:75