【剑指33】二叉搜索树的后序遍历序列

方法一:分治思想:时间 O( n 2 n^2 n2),空间 O(n)

题解:

  1. 利用后序遍历的规则:左树 | 右树 | 根节点,将后序遍历序列分成一个个子树
  2. 检查每一颗子树是否满足二叉搜索树的特性:左树都比根节点小
  3. 如果都满足则说明数组正确
  4. 缺点:每次遍历数组都只能检测一个根节点,因此检查所有根节点需要O( n 2 n^2 n2)的时间

时间:遍历一次数组只能减少一个节点,而每次遍历都需要O(n)时间
空间:当二叉树退化成单只树则需要O(n)的空间

class Solution {
public:
    bool verifyPostorder(vector<int>& postorder) 
    {
        // 1.后序遍历的规则:左支|右支|根节点
        // 2.因此只要满足每颗树都满足二叉搜索树的特性,则说明该数组正确
        // 3.利用分治思想将二叉树划分成一颗颗子树
        // 4.缺点:每次检查都要遍历二叉树,且一遍只能检查完成一个节点的正确性,时间复杂度O(n^2)
        return CheckTree(postorder, 0, postorder.size());
    }
    bool CheckTree(vector<int>& postorder, int left, int right)
    {
        if (left >= right)
            return true;
        int i = left;
        while (postorder[i] < postorder[right - 1])
            i++;
        int pos = i;
        while (postorder[i] > postorder[right - 1])
            i++;
        return (i == right - 1) && CheckTree(postorder, left, pos) && CheckTree(postorder, pos, right - 1);
    } 
};

方法二:单调栈:时间 O(n),空间O(n)

在这里插入图片描述

题解:

  1. 后序遍历的倒序:根节点 | 右树 | 左树
  2. 利用一个栈专门存储搜索树的左树,也就是比根节点小的节点
  3. 只要栈不空,检测到当前节点比栈顶元素小,则说明到达了根节点子树的一个左子树
  4. 一直出栈,直到栈空 或者 栈顶元素大于当前节点
  5. 根节点为最后一次出栈元素

注:第一次 root 节点可以看作INT_MAX的左子树,而右子树为空

时间:所有节点都入栈出栈一次,因此是O(n)
空间:单支树空间O(n)

class Solution {
public:
    bool verifyPostorder(vector<int>& postorder) 
    {
        // 1.单调栈:借助一个栈结构专门存储搜索树的右子树,也就是比根节点大的树
        // 2.只要栈不空,并且检测到当前节点比栈顶元素小,则说明到达了左子树
        // 3.一直出栈,直到栈空 或者 栈顶元素小于当前节点
        // 4.根节点为最后一次出栈元素
        stack<int> stc;
        int root = INT_MAX;
        for (int i = postorder.size() - 1; i >= 0; --i)
        {
            if (postorder[i] > root)
                return false;
            while (!stc.empty() && stc.top() > postorder[i])
            {
                root = stc.top();
                stc.pop();
            }
            stc.push(postorder[i]);
        }
        return true;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值