剑指 Offer 33. 二叉搜索树的后序遍历序列
输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 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 || postorder.length == 0) return true;
if (postorder.length == 1) return true;
int root = postorder[postorder.length - 1];
int leftSubTreeCount = 0;
while (postorder[leftSubTreeCount] < root) {
leftSubTreeCount++;
}
int[] leftArray = new int[leftSubTreeCount];
for (int i = 0; i<leftArray.length; i++) {
leftArray[i] = postorder[i];
}
int rightSubTreeCount = leftSubTreeCount;
while (rightSubTreeCount < postorder.length - 1) {
if (postorder[rightSubTreeCount] < root) {
return false;
}
rightSubTreeCount++;
}
int[] rightArray = new int[rightSubTreeCount];
for (int i = leftSubTreeCount; i<rightArray.length; i++) {
rightArray[i] = postorder[i];
}
return verifyPostorder(leftArray) && verifyPostorder(rightArray);
}
}
程序写出来了,但是效率并不高
优化
class Solution {
public boolean verifyPostorder(int[] postorder) {
//边界条件
if (postorder == null || postorder.length == 0) return true;
return verifyPostorder(postorder, 0, postorder.length - 1);
}
public static boolean verifyPostorder(int[] postorder, int left, int right) {
if (left >= right) return true;
int root = postorder[right];
//数组里面,左子树的右边界
int leftSubTreeRightIndex = left;
while (postorder[leftSubTreeRightIndex] < root) {
leftSubTreeRightIndex++;
}
//数组里面,右子树的右边界
int rightSubTreeRightIndex = leftSubTreeRightIndex;
for (int i = rightSubTreeRightIndex; i < right; i++) {
if (postorder[i] < root) {
return false;
}
}
return verifyPostorder(postorder, left, leftSubTreeRightIndex - 1) && verifyPostorder(postorder, leftSubTreeRightIndex, right - 1);
}
}