题目地址:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/
题目描述
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true
,否则返回 false
。假设输入的数组的任意两个数字都互不相同。
题目示例
参考以下这颗二叉搜索树:
5
/
2 6
/
1 3
示例 1:
输入: [1,6,3,2,5]
输出: false
示例 2:
输入: [1,3,2,6,5]
输出: true
解题思路
递归:分析题目,我们发现题目给的是二叉搜索树,对于二叉搜索树的特点我们需要知道,即二叉搜索树中根节点值大于其左子树中的任何一个节点的值,小于右子树中任何一个节点的值,它的左右子树也满足此条件。然后,考虑二叉树后序遍历特点,即节点访问顺序为“左子树->根节点->右子树”。这样我们就自然而然的想到第一种解题方法,即结合二叉搜索树的定义以及后序遍历来实现,具体可采用递归分治方法判断二叉搜索树的所有子树是否满足二叉搜索树的定义,如果所有子树均正确,则返回true,表明此序列是二叉搜索树的后序遍历序列。
栈:利用镜像解决,即二叉搜索数按照“根节点->右子树->左子树”来遍历访问,比如后序遍历序列为[1,3,2,6,5],则它的镜像[5,6,2,3,1],我们可以使用栈stack存储递增的节点,每次遇到值递减的节点r,则通过出栈来更新节点r的父节点root,每轮判断节点r和父节点root的关系,如节点r大于父节点root,则不满足二叉搜索树的条件,返回false,否则,满足二叉搜索树的定义,并继续遍历,当栈不为空,并且节点r小于栈顶元素时,执行出栈操作,将此节点赋给root。最后返回true。
程序源码
递归
class Solution { public: bool verifyPostorder(vector<int>& postorder) { if(postorder.size() < 2) return true; return check(postorder, 0, postorder.size() - 1); } bool check(vector<int>& postorder, int left, int right) { if(left >= right) return true; //子树节点数量小于2,即子树节点数为0或者1,直接返回true int root = postorder[right]; //根据"左、右、根"特点,获取二叉搜索树的根节点 int le = left; while(le < right && postorder[le] < root) le++; //遍历左子树,其值小于根节点,区间[left, le - 1] int ri = le; while(ri < right && postorder[ri] > root) ri++; //遍历右子树,其值大于根节点,区间[le, right - 1] return ri == right && check(postorder, left, le - 1) && check(postorder, le, right - 1); //递归遍历检查左右子树 /* int t = left; //划分左右子树区间为分别为[left, t - 1]、[t, right - 1] while(t < right && postorder[t] < postorder[right]) t++; //遍历寻找第一个大于根的节点,以此划分为左右子树区间,此位置后边均是大于根节点的数,即均在右子树中 for(int i = t; i < right; i++) { if(postorder[i] < root) return false; //判断根节点后续的区间中是否所有节点值均大于根节点,若有小于根的节点,返回false } if(!check(postorder, left, t - 1)) return false; //检查左子树 if(!check(postorder, t, right - 1)) return false; //检查右子树 return true;*/ } };
非递归(栈)
class Solution { public: bool verifyPostorder(vector<int>& postorder) { stack<int> sk; int root = INT_MAX; for(int i = postorder.size() - 1; i >= 0; i--) { if(postorder[i] > root) return false; while(!sk.empty() && sk.top() > postorder[i]) { root = sk.top(); sk.pop(); } sk.push(postorder[i]); } return true; } };
参考文章