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

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

https://www.nowcoder.com/practice/a861533d45854474ac791d90e447bafd?tpId=196&tqId=39722&rp=1&ru=/exam/oj&qru=/exam/oj&sourceUrl=%2Fexam%2Foj&difficulty=undefined&judgeStatus=undefined&tags=581&title=

方法一:

分治+递归

思路: 二叉树的后序遍历顺序是:左子树 -> 右子树 -> 根节点 因此序列的最后一个数代表了根节点 因此我们可以将一个序列划分为3段, 左子树+右子树+根, 例如[4, 8, 6, 12, 16, 14, 10]可以根据根节点的值将其划分为左子树[4, 8, 6], 右子树[12, 16, 14], 根[10], 由于我们是先确定的右子树区间, 因此当左子树区间中出现大于根节点的值时, 序列不合法, 我们再采用分治的思想, 对于每段序列代表的子树, 检查它的左子树和右子树, 当且仅当左右子树都合法时返回true

代码:

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
       int n=sequence.size();
       //如果是空树,题目约定空树不是二叉搜索树
       if(n==0) return false;
       //后序:左右根(分治思想)+递归(后序遍历和二叉搜索树的递归定义)
       return devide(sequence,0,n-1);
    }
    //分治+递归
    bool devide(vector<int>&a,int l,int r){
        //递归的结束条件:如果这棵树只剩下一个节点,就返回true
        if(l>=r) {
            return true;
        }
        //划分区间的最后一个节点为根节点
        int root=a[r];
        //划分右子树:由于如果该树是二叉搜索树,则右树的节点的值大于根节点的值
        int j=r-1;
        while(j>=0&&a[j]>root) j--;
        //剩下的就是左子树,如果左子树中有节点的值大于根节点的值,那么就不是二叉搜索树
        int i=l;
        for(i=l;i<=j;i++){
            if(a[i]>root){
                return false;
            }
        }
        //由于二叉搜素树的递归定义,所以需要判断一下左右子树是否为二叉搜索树
        return devide(a,l,j)&&devide(a,j+1,r-1);
    }
};

方法二:

二叉搜索树对应的中序遍历是升序 中序:入栈,后序:某一种出栈顺序

思路:实际上二叉树的中序遍历和后序遍历对应着一种栈的压入、弹出序列, 而对后序遍历序列从小到大排序就得到了中序遍历序列 我们得到中序遍历序列后, 将其作为入栈序列, 检查后序遍历序列是不是一个合法的出栈序列即可 对于检查栈的合法压入、弹出序列问题, 请看栈的压入、弹出序列题解

class Solution {
public:
    bool VerifySquenceOfBST(vector<int> sequence) {
      int n=sequence.size();
      //特判一下,题目约定空树不是二叉搜索树
      if(n==0) return false;
      //由于如果是二叉搜索树,那么其中序遍历是升序的
      vector<int> inorder(sequence);
      sort(inorder.begin(),inorder.end());
      return outorder(inorder,sequence);
    }
    //再将中序遍历压入栈中,看一下有没有满足后序的出栈顺序
    bool outorder(vector<int>inorder,vector<int>sequence){
        stack<int> stack1;
        int j=0;
        //遍历中序,将其对应的元素一个一个依次入栈
        //每入栈一个元素,就判断一下如果当前栈非空且栈顶元素与后序的元素对应,就出栈,并j++
        for(int i=0;i<inorder.size();i++){
             stack1.push(inorder[i]);
             while(!stack1.empty()&&stack1.top()==sequence[j]){
                j++;
                stack1.pop();
             }
        }
        //如果j==sequence.size(),就表明存在一种出栈顺序和后序遍历一致
        return j==sequence.size();
    }
};
全部评论

相关推荐

05-29 09:02
门头沟学院 Java
点赞 评论 收藏
分享
06-13 17:33
门头沟学院 Java
顺序不记了,大致顺序是这样的,有的相同知识点写分开了1.基本数据类型2.基本数据类型和包装类型的区别3.==和equals区别4.ArrayList与LinkedList区别5.hashmap底层原理,put操作时会发生什么6.说出几种树型数据结构7.B树和B+树区别8.jvm加载类机制9.线程池核心参数10.创建线程池的几种方式11.callable与runnable区别12.线程池怎么回收线程13.redis三剑客14.布隆过滤器原理,不要背八股,说说真正使用时遇到了问题没有(我说没有,不知道该怎么回答了)15.堆的内存结构16.自己在写项目时有没有遇见过oom,如何处理,不要背八股,根据真实经验,我说不会17.redis死锁怎么办,watchdog机制如何发现是否锁过期18.如何避免redis红锁19.一个表性别与年龄如何加索引20.自己的项目的QPS怎么测的,有没有真正遇到大数量表21.说一说泛型22.springboot自动装配原理23.springmvc与springboot区别24.aop使用过嘛?动态代理与静态代理区别25.spring循环依赖怎么解决26.你说用过es,es如何分片,怎么存的数据,1000万条数据怎么写入库中27.你说用limit,那么在数据量大之后,如何优化28.rabbitmq如何批次发送,批量读取,答了延迟队列和线程池,都不对29.计网知不知道smtp协议,不知道写了对不对,完全听懵了30.springcloud知道嘛?只是了解反问1.做什么的?短信服务,信息量能到千万级2.对我的建议,基础不错,但是不要只背八股,多去实际开发中理解。面试官人不错,虽然没露脸,但是中间会引导我回答问题,不会的也只是说对我要求没那么高。面完问我在济宁生活有没有困难,最快什么时候到,让人事给我聊薪资了。下午人事打电话,问我27届的会不会跑路,还在想办法如何使我不跑路,不想扣我薪资等。之后我再联系吧,还挺想去的😭,我真不跑路哥😢附一张河科大幽默大专图,科大就是大专罢了
查看30道真题和解析
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

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