【要求】输入一个序列,判断这个序列是不是某个二叉搜索树的后续遍历结果。
要判断,首先得分析起床二叉搜索树的后续遍历的特性。由于后续遍历是“左-右-根”,所以:
- 访问的最后一个节点实际上就是整棵二叉树的根节点root;
- 然后,找到大于根节点的最小节点 rightMin,在进行后续遍历的时候,rightMin 是右子树的第一个被访问的节点,所以 rightMin 前面的就是 root 的左子树,左子树的节点应该都比 root 小;
- 这个 rightMin 其实非常好找,因为按照后续遍历,前面第一批输出的左子树,所以,找到的第一个比 root 大的节点就是 rightMin;
- rightMin 和 root 之间的节点都是右子树的节点,所以,这些节点应该都比 root 大。
- 然后,二叉搜索树的子树也应该是二叉搜索树,所以在确定了子树的序列后,递归判断它们是不是后续遍历的结果就行了。
/**
* 判断一个序列是不是某一个二叉搜索树的后续遍历的结果
*/
public boolean isPostOrderTraveral(int[] array) {
return isPostOrderTraveral(array, 0, array.length - 1);
}
private boolean isPostOrderTraveral(int[] array, int begin, int end) {
// 只有一个节点为true
if (begin == end) {
return true;
}
int root = array[end];
// 考虑到没有右子树的情况
int rightMin = root;
int indexOfRightMin = end;
for (int i = 0; i < end; i++) {
if (array[i] > root) {
rightMin = array[i];
indexOfRightMin = i;
break;
}
}
// 找到 rightMin 之后,它之前的部分必须都小于root
// 但是上面的查找已经利用了这一性质,也就保证了这一性质,所以不用重复判断
// rightMin 之后到 root 之间的部分是右子树,必须全部大于 root
for (int i = indexOfRightMin + 1; i < end; i++) {
if (array[i] < root) {
return false;
}
}
boolean leftTree;
if (indexOfRightMin != 0) {
leftTree = isPostOrderTraveral(array, begin, indexOfRightMin - 1);
} else {
leftTree = true;
}
// rightMin 之后,root 之前,包括 rightMin 本身,都是右子树的节点
boolean rightTree;
if (indexOfRightMin < end) {
rightTree = isPostOrderTraveral(array, indexOfRightMin, end - 1);
} else {
rightTree = true;
}
return leftTree && rightTree;
}
测试:
public static void main(String[] args) {
/**
* 通过插入新建了一个二叉搜索树
* 8
* / \
* 3 22
* \ / \
* 5 13 27
* \
* 7
* */
TreeNode binarySearchTree = new TreeNode(8);
BinaryTreeTest testTree = new BinaryTreeTest();
testTree.add(binarySearchTree, 22);
testTree.add(binarySearchTree, 3);
testTree.add(binarySearchTree, 13);
testTree.add(binarySearchTree, 5);
testTree.add(binarySearchTree, 7);
testTree.add(binarySearchTree, 27);
ArrayList<TreeNode> aList = testTree.postorderTraveral(binarySearchTree);
System.out.println("后续遍历的结果是:");
int[] array = new int[aList.size()];
int count = 0;
for (TreeNode treeNode : aList) {
array[count] = treeNode.val;
System.out.printf("%-5d", array[count]);
count++;
}
System.out.println();
boolean ret1 = testTree.isPostOrderTraveral(array);
System.out.println("Is is a postorderTraveral array? " + ret1);
}
输出:
后续遍历的结果是:
7 5 3 13 27 22 8
Is is a postorderTraveral array? true