问题:给定一个整数数组,确定它是否可以是BST的后序遍历序列。例如:[5, 7, 6, 9, 11, 10, 8]
返回true,但[7, 4, 6, 5]
返回false。
我想知道我们是否可以在线性时间内完成此操作。以下是我提出的N^2
和NlgN
的解决方案。
N^2 solution
:扫描数组并检查根的左右子树值是否分别小于和大于根值。对每个子树重复一次。
NlgN solution
:构建从输入数组右侧到左侧的BST。跟踪我们可以在任何时候遇到的最大数量。每次插入左子节点时,此最大数量都会更新到父节点。如果我们尝试插入大于跟踪的最大数量的节点,我们可以返回false。
答案 0 :(得分:2)
这是一个线性时间算法,比这个答案的最后修订版简单得多。
def checkbst(lst):
# stack contains the values of nodes from which the current path departs right
stack = [float('-inf')]
# upperbound is the value of the leafmost node from which the path departs left
upperbound = float('inf')
for x in reversed(lst):
# pop stack elements greater than or equal to x
# stack[-1] is the top
while stack[-1] >= x:
upperbound = stack.pop()
if x >= upperbound:
return False
# push
stack.append(x)
return True
可以想象一个递归过程,它使用根值最后的事实如下。从右向左扫描,直到找到小于根的值。在该值之后拆分数组的最大正确前缀。递归验证右半部分。验证左半部分中的值是否小于根,然后递归地验证一半。
后一个递归处于尾部位置,可以转换为迭代。可以推迟检查值小于根的检查,因为上限随时间单调减小。我们在stack
中保留了递归堆栈的剩余部分,即我们进行非尾递归的根值序列。内部循环确定调用堆栈应考虑当前元素的程度。它是摊销的固定时间。
答案 1 :(得分:1)
这是C ++代码
bool verifyPostorder(vector<int>& nums)
{
int high=INT_MAX,index=nums.size();
for(int j=int(nums.size())-1;j>=0;--j)
{
if(nums[j]>high)return false;
while(i<=int(nums.size())-1 && nums[j]<nums[i])
high=nums[i++];
nums[--i]=nums[j];
}
return true;
}
你可以尝试根据这个来编写verifyPreorder。