在线性时间内创建图案化阵列 [重复]

Posted

技术标签:

【中文标题】在线性时间内创建图案化阵列 [重复]【英文标题】:Creating a patterned array in linear time [duplicate] 【发布时间】:2014-08-04 14:32:19 【问题描述】:

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

在 P[1..i-1] 中大于 P[i] 的成员中,我们选择索引最大的 P[k] (1

显然,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] 的最高索引数。 -->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

我说对了吗?

【问题讨论】:

@user3386109 在这种情况下不是解决了前一个问题吗?对我来说看起来不像是骗子。 我之前已经浏览过另一个问题 - 我将编辑我的问题以进一步澄清为什么它不重复。 @user3386109 这个问题和另一个问题的唯一区别是你从数组的end开始迭代到开头。 我明白了,这确实是我的疏忽。 【参考方案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

我在这里假设您只使用了 >= 0 的值,但如果您得到负值 highest 应该使用可能的最小值进行初始化。

【讨论】:

很有趣,但如果我理解正确,这将始终分配大于我们与之比较的值的最大值。该问题需要分配最高的 indexed 数字,该数字比我们与之比较的数字具有更大的价值。还是我把你的代码弄错了? 不,您确实是对的,我会尝试根据相同的想法考虑索引来寻找答案。 我还没有找到O(n) 用我的基本想法解决这个问题的方法,你应该考虑接受 dubov94 的回答。此外,如果有人对此投反对票,我将能够删除此答案(对吗?)【参考方案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)

我假设searchP[i] 返回S[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 unoptimized(为了简单起见也没有检查一些不存在的顶点情况,小心!)目的是为了给你一个大致的想法。我们从 BST 的根目录开始,并在需要时按照通常的规则更新maxIndex(参见下面的说明)。我们 BST 的每个叶子(实际上代表一些 P[x])包含 5 个字段:

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

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

同样,让我们​​假设我们有curVertex.value &gt; value,这将我们引导到左子树。但是这次右子树的任意vertex.value都是vertex.value &gt; 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

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

总的来说,我们有n 的主循环迭代和log n 用于insertsearch 调用,所以最终的复杂度是O(n log n)。

【讨论】:

这已经是一个很大的改进了,我会等着看是否有人能提出一个 O(n) 的想法,仍然。

以上是关于在线性时间内创建图案化阵列 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

将两个项目限制在线性布局内的顶部和底部

在线性时间和恒定空间中查找数组中缺失和重复的元素

在线性时间内查找长度为 N、数字 1 到 N-1 的数组中的重复项,而无需使用额外的 obj/arr 来跟踪计数

在线性布局中对齐元素

如何在线性布局中保持 TextView 为中心

ImageView 未在滚动视图内的线性布局中显示