滴滴一面 | #二叉搜索树的后序遍历序列#

二叉搜索树的后序遍历序列

https://www.nowcoder.com/practice/a861533d45854474ac791d90e447bafd

递归

一棵二叉树是二叉搜索树(BST)的充分必要条件是:

  • 它根节点的左子树是一棵BST;
  • 它根节点的右子树是一棵BST;
  • 它根节点的值大于左子树的最大值,小于右子树的最小值。

当前数组的尾部一定是二叉树的根节点,我们需要将当前数组除去尾部元素后的部分分为两段,划分规则就是上述的第三点:我们先找到右子树区间(可以为空)(右子树区间是按照规则找的,所以无需再次验证了),再去验证前面剩下的部分(可以为空)是否都小于根节点。然后再依次递归验证第一点和第二点。

class Solution {
    bool VerifyHelper(vector<int>& sequence, int l, int r) {
        if (l >= r) {
            return true;
        }

        int root = sequence[r - 1];
        int i = r - 2;
        while (sequence[i] >= root) {
            i--;
        }

        int j = i;
        for (; j >= l; --j) {
            if (sequence[j] >= root) {
                return false;
            }
        }

        return VerifyHelper(sequence, l, i + 1) &&
            VerifyHelper(sequence, i + 1, r - 1);
    }

public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        if (sequence.empty()) {
            return false;
        }
        return VerifyHelper(sequence, 0, sequence.size());
    }
};

单调栈

首先回顾一下前序、中序、后序遍历,这里借助一下CS61B的课件:

后序遍历的顺序实际上是逆时针经过每个节点的右侧的顺序,如果我们反着遍历数组,那么就是顺时针经过节点右侧的顺序。

在逆向遍历数组的过程中,我们维护一个递增的单调栈:

  • 如果当前元素比栈顶大:我们正在向右侧走,入栈;
  • 如果当前元素小于栈顶:我们进入了一个节点的左子树:
  • 通过循环出栈比当前节点大的元素找到该节点
class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
        // 处理序列为空情况
        if(sequence.size() == 0) return false;
        
        stack<int> s;
        int root = INT_MAX;
        // 以根,右子树,左子树顺序遍历
        for(int i = sequence.size() - 1; i >= 0; i--) {
            if(sequence[i] > root) return false;
            
            while(!s.empty() && sequence[i] < s.top()) {
                root = s.top();
                s.pop();
            }
            // 每个数字都要进一次栈
            s.push(sequence[i]);
        }
        return true;
    }
};

全部评论

相关推荐

评论
点赞
1
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务