题目
剑指 Offer 33. 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。
参考以下这颗二叉搜索树:
5
/ \
2 6
/
1 3
示例 1:
输入: [1,6,3,2,5]
输出: false
示例 2:
输入: [1,3,2,6,5]
输出: true
提示:
数组长度 <= 1000
分析
首先我们先看二叉搜索树的一些特点,第一点就是左子树的值都应该小于根节点的值,右子树的值都应该大于根节点的值。
先找到分界点mid,然后start-mid-1的是是左子树,mid-end-1的是右子树,右子树的数据都应该满足大于根节点的值条件。
这样就可以把原问题转化为递归子问题,利用递归方法即可解决问题。流程图如下:
代码如下方:
package leetcode.editor.cn;
public class POffer33 {
public static void main(String[] args) {
int[] postorder = new int[]{1,2,5,10,6,9,4,3};
POffer33 p = new POffer33();
boolean b = p.verifyPostorder(postorder);
System.out.println("result " + b);
}
public boolean verifyPostorder(int[] postorder) {
return recursive(postorder, 0, postorder.length - 1);
}
// 左子树的值都小于二叉搜索树的根,右子树的值都大于二叉搜索树的根
private boolean recursive(int[] postorder, int start, int end) {
if (start >= end) {
return true;
}
// 根 是最后的值.
int root = postorder[end];
int mid = -1;
for (int i = start; i < end; i++) {
if (postorder[i] > root) {
// 一旦首次大于根,那么这个值就应该是右子树的数
mid = i;
break;
}
}
if (mid == -1 || mid == end - 1) {
return recursive(postorder, start, end -1 );
}
for (int i = mid; i < end; i++) {
// 右子树理论上应该都会大于根,所以一旦出现小于根的,那么他一定不符合二叉搜索树的后续遍历
if (postorder[i] < root) {
return false;
}
}
boolean recursiveLeft = recursive(postorder, start, mid - 1);
if (!recursiveLeft) {
return false;
}
boolean recursiveRight = recursive(postorder, mid, end - 1);
if (!recursiveRight) {
return false;
}
return true;
}
}