剑指Offer 33 - 二叉搜索树的后序遍历序列

题目描述

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

思路

递归:根结点为数组最后一个元素,找到第一个大于根节点的元素,以此划分左右子树。验证左(右)子树节点是否全部小于(大于)根结点,再递归验证左右子树是否为二叉搜索树。

要点

递归终止条件:i >= j,验证到叶子结点或该区间没有节点,直接返回true

递归工作:

划分左右子树: 遍历[i,j-1]区间,直到找到第一个大于root的元素,索引记为m。则[i, m-1]属于左子树,[m, j]属于右子树。

PS: 若没有左子树,即所有元素都大于root,则m===i, 下一层递归时左子树recursion(i, i-1)会出现 i > j, 所以终止条件是>=不是===

      若没有右子树,即所有元素都小于root,则m===j,下一层递归recursion(i, j-1)和recursion(j, j)

判断是否为二叉搜索树:

左子树[i, m-1]所有节点都小于root,第一步划分左右子树时已验证过
右子树[m,j−1] 所有节点都应大于root, while循环遍历检查,若在验证到j-1之前提前退出则不满足。

 

另一种描述:可以理解为遍历[i, j-1]的每一个节点,逐个验证与根节点的大小关系,在第一比根节点大的元素之后的所有元素必须全部大于根节点。

 

代码

/**
 * @param {number[]} postorder
 * @return {boolean}
 */
var verifyPostorder = function(postorder) {
    
    if(!postorder || !postorder.length) return true;
    return recursion(0, postorder.length-1);
    
    function recursion(i, j){
        if(i >= j) return true;
        
        const root = postorder[j];
        let verifyP = i;
        
        //划分左右子树 + 验证左子树是否全部小于root
        while(verifyP < j && postorder[verifyP]<root){
            verifyP++;
        }
        
        //记录右子树起点
        let rightStart = verifyP;
        
        //验证右子树是否全部大于root
        while(verifyP < j && postorder[verifyP]>root){
              verifyP++;
        }
        if(verifyP !== j){
            return false;
        }
        
        return recursion(i, rightStart-1) && recursion(rightStart, j-1);
    }
    
};

猜你喜欢

转载自www.cnblogs.com/xintangchn/p/13190121.html