目录
题目
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true
,否则返回 false
。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
5 / \ 2 6 / \ 1 3
示例 1:
输入: [1,6,3,2,5] 输出: false
示例 2:
输入: [1,3,2,6,5] 输出: true
提示:
数组长度 <= 1000
后续遍历定义:遍历顺序:左、右、根
二叉搜索树定义:
二叉搜索树的左右子树也是二叉搜索树;
根节点值大于左子树中所有结点的值;
根结点值小于右子树中所有结点值;
递归写法分析
由于后续遍历根节点是最后遍历的:所以数据末尾元素就是根节点,找到大于末尾元素的第一个整数就可以切分出左右子树。
递归对切分出的两个数组,左边部分均小于末尾元素、左边均大于末尾元素。就满足符合二叉搜索树的后续遍历结果。
反过来说:只要左边存在一个值比当前末尾元素大,或者右边存在一个值比当前末尾元素小,那该数组就不符合二叉搜索树的后续遍历结果。
递归写法代码
class Solution { public boolean verifyPostorder(int[] postorder) { // 边界判断 if(postorder == null){ return true; } return f(postorder,postorder.length-1); } /** * * @param postorder * @param i 大于或等于当前根结点值的下标 * @param j 当前根节点下标 * @return boolean 值 */ public boolean f(int[] postorder ,int i ,int j){ // 当传入的树只有一个结点时,结束递归 if(i>=j){ return true; } int root = postorder[j]; int p =i; // 拿到第一个大于或等于root的值的位置 while(postorder[p]<root){ p++; } // 判断p到j-1的范围是否存在小于root的元素 for(int k=p; k<=j-1;k++){ if(postorder[k]<root){ return false; } } // 判断 i到p-1,是否存在大于root的元素 for (int k = p; k <=p-1 ; k++) { if(postorder[k]>root){ return false; } } return f(postorder,i,p-1)&&f(postorder,p,j-1); } }
执行结果:
使用辅助栈写法分析
逆序遍历数组
若栈为空,就将当前元素压栈;
栈不为空,比较当前元素与栈顶元素
cur>stack.peek():说明此时是右结点、元素继续入栈
cur<stack.peek():遇到了左结点,为了到此时的的父节点、需要不断更新栈顶元素;
使用辅助栈代码
class Solution { public boolean verifyPostorder(int[] postorder) { // 边界判断 if(postorder==null){ return true; } Stack<Integer> stack = new Stack<>(); int parent = Integer.MAX_VALUE; for (int i = postorder.length-1; i >=0 ; i--) { int cur = postorder[i]; // 若cur小于当前栈顶元素,移除栈顶元素,且更改root的值 // 找到父节点 while (!stack.isEmpty() && stack.peek()>cur) { parent = stack.pop(); } // parent 父节点或某祖先结点 if(cur>parent){ return false; } stack.add(cur); } return true; } }