我得到了一个数组(由n个元素组成),我必须在每个元素的右侧找到比自身大的最小元素(当前元素)。
For example :
Array = {8,20,9,6,15,31}
Output Array = {9,31,15,15,31,-1}
是否可以在O(n)
中解决此问题。我想到从右侧(从n-2开始)遍历数组并为其余元素构建平衡二叉搜索树,因为在其中搜索一个立即大于当前元素的元素元素将是O(logn)。
因此时间复杂度将为O(n *(log(n))。
有没有更好的方法解决这个问题?
答案 0 :(得分:6)
您提出的问题无法在O(n)
时间内解决,因为您可以减少对它的排序,从而在O(n)
时间内实现排序。
假设存在一种解决O(n)
中问题的算法。
让一个元素 a 。
该算法还可用于查找最小元素更大,更大而不是 a (在运行算法之前通过反转数组)。 它还可用于查找最大元素右侧(或左侧)和小型元素 (通过在运行算法之前否定元素)。
因此,在运行算法四次(线性时间)后,您知道哪些元素应位于每个元素的右侧和左侧。为了在线性时间内构造排序数组,您需要保留元素的索引而不是值。您首先通过遵循"大于指针"来找到最小的元素。在线性时间内,然后在另一个方向上再次传递以实际构建数组。
答案 1 :(得分:3)
其他人已经证明通常不可能在O(n)中解决。
但是,可以在O(m)中进行,其中m是最大元素的大小。
这意味着在某些情况下(例如,如果您的输入数组已知是整数1到n的排列),则可以在O(n)中进行。
下面的代码显示了基于计算下一个更大元素的标准方法的方法。 (这种方法有一个很好的解释on geeks for geeks)
def next_greater_element(A):
"""Return an array of indices to the next strictly greater element, -1 if none exists"""
i=0
NGE=[-1]*len(A)
stack=[]
while i<len(A)-1:
stack.append(i)
while stack and A[stack[-1]]<A[i+1]:
x=stack.pop()
NGE[x]=i+1
i+=1
return NGE
def smallest_greater_element(A):
"""Return an array of smallest element on right side of each element"""
top = max(A) + 1
M = [-1] * top # M will contain the index of each element sorted by rank
for i,a in enumerate(A):
M[a] = i
N = next_greater_element(M) # N contains an index to the next element with higher value (-1 if none)
return [N[a] for a in A]
A=[8,20,9,6,15,31]
print smallest_greater_element(A)
我们的想法是以更大的索引查找大小顺序的下一个元素。因此,下一个元素将是出现在右侧的最小元素。
答案 2 :(得分:2)
这不能在O(n)
中完成,因为我们可以减少Element Distinctness Problem(在比较基础上已知在Omega(nlogn)中是可以的)。
首先,让我们对这个问题做一点扩展,这不会影响它的硬度:
我得到了一个数组(n个元素),我必须找到 每个元素右侧的最小元素,大于/等于 比它本身(当前元素)。
添加是我们允许元素等于它(和右边),而不仅仅是严格地大于 1 。
现在,给定元素清晰度arr
的实例,针对此问题运行算法,并查看是否存在i
元素arr[i] == res[i]
,如果没有&#39;回答&#34;所有不同的&#34;,否则:&#34;并非所有不同&#34;。
但是,由于Element Distinctness基于Omega(nlogn)
比较,因此很容易出现这个问题。
(1)
为什么添加相等性不会使问题变得更加困难的一个可能的理由是 - 假设元素是整数,我们可以只将i/(n+1)
添加到数组中的每个元素,现在对于每两个元素arr[i] < arr[j]
,也{ {1}},但如果是arr[i] + i/(n+1) < arr[j] + j/(n+1)
,那么如果arr[i] = arr[j]
i<j
,我们可以使用相同的算法来解决问题的同等性。