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

题目描述

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

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

     5
    / \
   2   6
  / \
 1   3

示例:

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

解题思路

首先,要明确两个性质:

  1. 二叉搜索树,左子树节点最大值 < 根节点值 < 右子树节点最大值,且左、右子树亦为二叉搜索树;
  2. 后续遍历:数组内顺序为左、右、根。其中左、右可能为空、单节点、复数节点(嵌套左、右、根)。

因此,思路就很简单了:

  1. 根据后续遍历数组从大维度向小维度划分数组(左子树、右子树、根节点),即分治思想!
  2. 遍历检查,左子树所有节点数值应小于根节点,右子树所有节点数值应大于根节点。
  3. 递归第一步划分后的左右子树。

实现细节:

  • 划分子树,从右向左划分,最右边一定为根节点,遇到一个小于根节点值的节点前的子数组即为右子树,剩余为左子树;
  • 由于划分过程,右子树一定合法,因此只需检查左子树;
  • 返回结果需要左右子树都合法,因此使用 && 连接。

代码实现

class Solution {
    
    
public:
    bool verifyPostorder(vector<int>& postorder) {
    
    
        return dfs(postorder, 0, postorder.size());
    }

    bool dfs(vector<int>& postorder, int begin, int end){
    
    
        if(end - begin <= 1) return true;
        int temp = postorder[end - 1];
        int posi = end - 2;
        
        for(; posi >= 0; posi--){
    
    
            if(postorder[posi] < temp) break;
        }

        for(int i = posi; i >= 0; i--){
    
    
            if(postorder[i] > temp) return false;
        }

        return dfs(postorder, begin, posi + 1) && dfs(postorder, posi + 1, end - 1);
    }
};

运行结果:

在这里插入图片描述

使用单调栈可能性能上会有提升,这个我们以后再讲。

猜你喜欢

转载自blog.csdn.net/LogosTR_/article/details/125721165