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

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

题目:
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同

思路:
这个题有两种解法,先介绍第一种方法
我们知道后序遍历是 左右根的顺序,所以数组的最后一个元素就是根。
二叉搜索树的特点是,左子树的值小于根,右子树的值大于根。
所以需要在数组中,先找到小于根结点的一部分结点,记住分界点m.【start,m-1】]是左子树数组。【m,end-1】就是右子树,遍历右子树数组中的值,如果有小于根结点的,返回FALSE。
左右子树分别递归查找,只有左子树和右子树同时满足是二叉树,整棵树才是二叉搜索树。
代码如下:

 bool verifyPostorder(vector<int>& postorder) {
        /* 
        数组最后一个元素的前一个元素如果小于当前值,则是左子树上的值,大于当前值就是右子树结点值
        不断递归循环判断。
        如果左子树上出现比根结点还大的值,就不是二叉搜索树
        同理,如果右子树上出现比根结点还小的值,也不是二叉搜索树
        */
        if(postorder.size()==0)  return true;

        return help(postorder,0,postorder.size()-1);

    }

	bool help(vector<int>& postorder,int start,int end){
	   
	   if(start == end) return true;
	   //根结点
	//    int len = postorder.size();
	   int root = postorder[end];
	   //在二叉搜索树中左子树结点的值小于根结点的值
	   int i=start;
	   for( ; i<end; i++){
	       if(postorder[i] > root){
	           break;
	       }
	   }
	   //在二叉搜索树中右子树结点的值大于根结点的值
	   int j=i;
	   for(; j<end; j++){
	       if(postorder[j] < root)
	           return false;
	   }
	
	   bool left=true;
	   bool right = true;
	
	   //判断左右子树是不是二叉搜索树
	   if(i>start){  //左子树不为空
	       left = help(postorder,start,i-1);
	   }
	   if(i<end){  //右子树不为空
	       right = help(postorder,i,end-1);
	   }
	   return (left && right);
  }

第二种方法:
最巧妙的是用单调栈的方法,访问后序遍历序列的倒序数组,变成了根右左的顺序,即先遍历根然后是右子树,最后是左子树。
构造单调递增栈,不断向右遍历,遍历到的值大于栈顶元素的值,则代表当前结点是右结点,则压入栈中。直到遇到一个小于当前栈顶元素的值,说明遍历到了左子树,需要在栈中找到当前左子树的父节点。怎么找呢? 如果栈不为空,就将栈顶值大于当前值的元素弹出来,直到栈顶元素小于当前值了(或者栈为空了),停止pop。并记录最后一次弹出的元素,即当前左子树的父节点,接下来的结点值都应该小于该父节点值。如果不满足,就返回false,若能顺利遍历完整个数组,则说明该数组满足条件!

代码如下:

 bool verifyPostorder(vector<int>& postorder) {
   //用单调栈的方法来做,时间和空间复杂度都是O(N)
        if(postorder.size()==0)  return true;  //当是空树时,默认也是正确的
        stack<int> st;
        //定义前一个父节点的值
        int preEle = INT_MAX;
        //用后续遍历的倒序数组来做,确认是单调的
        for(int i=postorder.size()-1; i>=0; i--){
            if(postorder[i] > preEle){
                return false;   //如果当前元素大于根结点,肯定就是错的
            }
            // 当当前节点的值小于父节点的值,说明遍历到了左子树上,所以要找到这个左子树							   的父节点
            //在栈中找到最后一个大于当前值的结点并记录下来
            while(!st.empty() && postorder[i] < st.top()){
                preEle = st.top();
                st.pop();
            }
            //如果,当前元素大于根结点的值 或者  栈为空,  将当前数据压入栈中
            st.push(postorder[i]);
        }
        
        //如果能遍历完整个数组,就是正确的
        return true;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值