在未排序的数组中,我们必须用右边的第一个元素替换每个元素,这个元素大于当前元素。如果右边的元素都不大,则应该用-1
替换。
示例:
3 1 2 5 9 4 8 should be converted to
5 2 5 9 -1 8 -1
我可以想到一个简单的解决方案,我们用整个数组检查每个元素,这是一个Ο(n²)解决方案。有更好的方法吗?
答案 0 :(得分:11)
主要思想是以相反的顺序(从右到左)处理数组。我们做了一些观察:
A[k] ≤ A[j]
,然后我们将元素 k 称为无关,因为它永远不会是任何元素 1,2,...,k的结果 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
是堆栈。
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
55,s.peek()&lt; 55,所以弹出元素,即32然后弹出下一个以及50&lt; 55,而不是推55.下一个更高的元素11 - 32。
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