在线性时间内创建图案化阵列 [重复]
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-StackNIL
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)
我假设search
为P[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 个字段:
那么什么时候需要呢?假设我们有curVertex.value <= value
。这意味着我们必须去正确的子树。左子树的任何vertex.value
也是<= value
,因此左子树和当前顶点中没有满足P[y] > P[new]
条件的顶点(P[y]
),因此我们不更改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
这里我没有再次检查children是否存在,还添加了parent
字段。 BST.insertNode
只是一个基本的 BST 插入方法,它返回给我们一个新的顶点对象。之后我们就向上到根,为路径上的每个顶点更新.subtreeMaxIndex
。
总的来说,我们有n
的主循环迭代和log n
用于insert
和search
调用,所以最终的复杂度是O(n log n)。
【讨论】:
这已经是一个很大的改进了,我会等着看是否有人能提出一个 O(n) 的想法,仍然。以上是关于在线性时间内创建图案化阵列 [重复]的主要内容,如果未能解决你的问题,请参考以下文章