在线性时间内创建图案化阵列

时间:2014-06-14 00:10:33

标签: arrays algorithm stack time-complexity pseudocode

  

给定整数数组P [1..n],我们要构建一个数组S [1..n]:

     

在P [1..i-1]中比P [i]大的成员中,我们选择具有最大索引的P [k](1 <= k

显然,S []中的第一个元素将为0,因为之前没有元素。其他人可以通过数组P []的迭代找到,但是,这将是O(n^2),因为它是系列1+2+...+n=[1/2n(n+1)]的总和。

有没有办法在线性时间内完成此操作?我已经考虑过使用 stacks ,因为它有助于提取具有更大值的最高索引,但是,我试图实现它的任何方式仍然需要我通过创建的堆栈,所以它是实际上更糟糕 - 创建堆栈的时间,以及到达所需元素的时间,一遍又一遍。也许还有另一种方式?

有关如何完成的任何想法/建议/提示?

示例:

P[5,4,9,7,8]-->S[0,5,0,9,9]
P[1,5,2,3]-->S[0,0,5,5]

澄清:

我们应该为S [i]指定最高索引数字,仍然大于P [1..i-1]中的P [i]。例如,假设P [8,2,1]。虽然8是最大值,但S [3]将保持值2,因为它是仍然大于P [3]的最高索引数。 - &GT; S [0,8,2]

修改

我相信我有一个O(n)解决方案,使用堆栈。伪代码的想法:

BuildS(P[])
    Temp-StackNIL
    for(i<--1 up to n)
        while(Temp-Stack≠NIL)
            if(P[i]<=top[Temp-Stack])
                pop(Temp-Stack) //goes back to while
            else
                S[i]<--top[Temp-Stack]
                push(Temp-Stack,P[i]) //goes back to for
        S[i]<--0 //out of while
        push(Temp-Stack,P[i]) //goes back to for

我说得对吗?

2 个答案:

答案 0 :(得分:2)

我认为没有O(n)解决方案,尽管我提出了O(n log n)。

假设我们有binary search tree(BST)。主循环伪代码:

for i in [0, len(P)):
    S[i] = BST.search(P[i])    
    BST.insert(P[i], i)

我认为search会为S[i]返回P[i]

def search(value):

    def getSbyIndex(index):
        return index == -inf ? 0 : P[index]

    curVertex = BST.root
    maxIndex = -inf
    while:
        if curVertex.value > value:
            if !(curVertex.leftChild exists):
                return getSbyIndex(maxIndex)
            else:
                maxIndex = max(maxIndex, curVertex.index, curVertex.rightChild.subtreeMaxIndex)
                if curVertex.leftChild.value <= value:
                    return getSbyIndex(maxIndex)
                else:
                    curVertex = curVertex.leftChild
        else:
            if !(curVertex.rightChild exists):
                return getSbyIndex(maxIndex)
            else:
                curVertex = curVertex.rightChild

为了简单起见,我写了search未优化(并且也没有检查一些不存在的顶点情况,为了简单起见,小心!),以便给出一般的想法。我们从BST的根开始,在需要时更新maxIndex的常规规则(请参阅下面的说明)。我们BST的每个叶子(实际上代表一些P [x])包含5个字段:

  • leftChild
  • rightChild
  • 值(即P [x])
  • index(x)
  • subtreeMaxIndex(以当前顶点为根的子树顶点中的.index的最大值)

那么什么时候需要?假设我们有curVertex.value <= value。这意味着我们必须转到正确的子树。左子树的任何vertex.value也是<= value,因此左子树和当前顶点中没有顶点(P[y]),因此满足P[y] > P[new]条件,因此我们不会更改maxIndex

同样地,让我们假设我们有curVertex.value > value,它将我们引向左侧子树。但是这次右侧子树的任何vertex.value都是vertex.value > value,因此当前和右侧子树顶点中的所有P[y]实际上都大于P[new],所以我们必须找到它们的最大索引,等于max(curVertex.index,curVertex.rightChild.subtreeMaxIndex),并尝试用它更新maxIndex

我们需要的最后一件事是insert

def insert(value, index):
    newVertex = BST.insertNode(value)
    newVertex.index = index
    curVertex = newVertex
    while curVertex is not BST.root:
        curVertex.subtreeMaxIndex = max(curVertex.index, curVertex.leftChild.subtreeMaxIndex, curVertex.rightChild.subtreeMaxIndex)
        curVertex = curVertex.parent

在这里,我没有再检查孩子是否存在,还添加了parent字段。 BST.insertNode只是一个基本的BST插入方法,它返回一个新的顶点对象。之后,我们只需向上移动到根,为路径上的每个顶点更新.subtreeMaxIndex

总的来说,对于nlog n调用,我们对主循环insert进行了search次迭代,因此最终的复杂度为O(n log n)。

答案 1 :(得分:1)

O(n)

实际上有一个解决方案

我们的想法是在循环P时跟踪遇到的最高值,并将P[i]与此值进行比较。

这是我提出的伪代码(使用你的第一个例子)

P = [1,5,2,3]
S = []
highest = 0

for i in P
    if highest < P[i]
        highest = P[i]
        S[i] = 0
    else
        S[i] = highest

我在这里假设你只使用值&gt; = 0但是如果你得到负值highest应该用尽可能小的值初始化。