是否有线性解决方案来确定后序列是否是有效的BST?

时间:2014-08-18 01:19:08

标签: performance algorithm data-structures tree binary-search-tree

问题:给定一个整数数组,确定它是否可以是BST的后序遍历序列。例如:[5, 7, 6, 9, 11, 10, 8]返回true,但[7, 4, 6, 5]返回false。

我想知道我们是否可以在线性时间内完成此操作。以下是我提出的N^2NlgN的解决方案。

N^2 solution:扫描数组并检查根的左右子树值是否分别小于和大于根值。对每个子树重复一次。

NlgN solution:构建从输入数组右侧到左侧的BST。跟踪我们可以在任何时候遇到的最大数量。每次插入左子节点时,此最大数量都会更新到父节点。如果我们尝试插入大于跟踪的最大数量的节点,我们可以返回false。

2 个答案:

答案 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。