码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2020-03-20 10:35:46      阅读:43      评论:0      收藏:0      [点我收藏+]

标签:相同   mic   block   情况   执行   display   http   关系   创建   

1:题目描述

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

 

参考以下这颗二叉搜索树:

     5
    /    2   6
  /  1   3

示例 1:

输入: [1,6,3,2,5]
输出: false

示例 2:

输入: [1,3,2,6,5]
输出: true

 

提示:

  1. 数组长度 <= 1000

2:题目分析

  首先作为二叉排序树的后序遍历来说,最后输出的为根节点。以下二叉排序树为例讲解,其输出的后序遍历为

技术图片

 

[1,3,2,6,5],如果该序列要满足是二叉树排序的后序遍历要求,则应该每一个节点的左子树小于该节点,有子树大于该节点的值,这样子才能确定是不是后序遍历,既要满足后序遍历的要求,又要满足二叉排序树的要求。

思路流程:

  1. 首先在目标序列中,确定当前序列中的左子树区间,右子树区间和根节点。按照后序遍历的特性,很显然当前序列的最后一个元素即为根节点,那如何确定左右子树区间尼?显然由于所有右子树都大于根节点,左子树小于根节点,所以按照该特性去遍历当前序列,划分左右子树区间。
  2. 在得到左右子树区间后,在按照上面逻辑分别处理左右子树,形成递归处理,如果都能划分处满足要求的左右子树区间,则可以判断是不是后序遍历。

递归三要素:

  1. 本轮递归终止条件:当前子树区间[i,j]中左端点大于等于右端点时,代表当前区间已经是满足后序遍历,直接return true。退出本次递归。
  2. 递归工作:根据当前区间的尾部数据,划分左右子区间,然后先向左子树递归,再向右子树递归。具体做法如下;
    1. 从区间[i,j]头开始,确定第一个大于尾部数据的数的位置,依次为左右子树的分界点。
    2. 然后判断如果该数前面所有数据都小于胃部,则前面满足左子树小于根节点,如果该位置后所有数据都大于尾部,则满足右子树大于根节点。否则该区间不满足二叉排序树,直接return false;
  3. 返回值:当所有子树都判断正确为二叉排序树的后序遍历时,才能算正确,所以用&&的关系。

3:代码实现

class Solution {
    int[] postOrder = null;
    public boolean verifyPostorder(int[] postorder) {
        postOrder = postorder;
        return recur(0,postOrder.length-1);
    }
    //递归方法,判断当前区间序列是不是二叉排序树的后序遍历

    //本轮递归终止条件:i>=j时,意味着当前区间缩小成为为0,则应该直接return true。退出本次递归

    //递归逻辑:首先把当前区间划分为左右子树的位置,然乎判断是不是左子树都小于根节点,右子树大于根节点
    //如果满足,则继续以当前左右子树区间继续递归,判断,否则直接return false。直到所有节点的左右子树都满足二叉排序树才行。

    //递归返回值:当且仅当当前区间左右子树都为二叉树后序遍历时才能return true
    public boolean recur(int i,int j){
        //本轮终止条件
        if(i>=j) return true;
        int m=i;//初始值为i,记录当前左右子树的划分点位置。
        //寻找左右子树划分点
        while(true){
            //如果当前i位置的值一旦大于尾部的根节点,则找到了划分左右子树的节点位置,break即可
            if(postOrder[m]>=postOrder[j]){
                break;
            }
            m++;
        }
        //则此时,[i,m-1]为左子树区间,[m,j-1]为右子树区间,j为根节点。
        //接下来判断该左右子树划分点,是不是满足左子树都小于根节点,右子树都大于根节点
        //由于我们再求得m位置时,就是通过小于根节点的条件求得的,所以可以直到所有左子树都是小于根节点的。
        //下面判断是不是所有右子树都大于根节点尼?
        int a = m;
        while(true){
            //如果到了j位置,依然满足大于根节点,则break,继续执行。
            if(a==j){
                break;
            }
            //一旦出现小于根节点的情况,则直接return fasle代表当前区间不是二叉排序树的后序遍历序列
            if(postOrder[a]<postOrder[j]){
                return false;
            }
            else{
                a++;
            }
        }
        //经过前面的判断,知道当前区间是满足二叉排序树的后序遍历,所以开始向其内部的子节点判断是不是二叉排序树的后序遍历
        return recur(i,m-1)&&recur(m,j-1);
    }
}

小小心得:对于这种递归返回值是boolean类型的递归方法。所有return false的情况都可以单独列出来,而为了return true的条件假设又多个,则可以通过return s1&&s2&&s3&&s4......等等将所有的条件向与,其含义是指当所有这些条件都满足时,才能return true!当其中一个条件不能满足是,return false。当然你也可以这样写,将所有情况的分别判断是直接return false,还是可以继续判断后序条件,这样写的逻辑没问题,但是比较繁琐了,冗长!!加油。

 

  • 添加到短语集
     
    • 没有此单词集:中文(简体) -> 中文(简体)...
       
    • 创建新的单词集...
  • 拷贝

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

标签:相同   mic   block   情况   执行   display   http   关系   创建   

原文地址:https://www.cnblogs.com/dazhu123/p/12529872.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!