根据后序数组重建搜索二叉树
根据后序数组重建搜索二叉树
《程序员代码面试指南》第45题 P148 难度:士★☆☆☆
原问题为判断数组arr是否可能是搜索二叉树后序遍历的结果,进阶问题为通过数组arr重构二叉树。
原问题的解法:根据二叉树后序遍历的顺序——左-右-根,头节点的值一定是数组的最后一个元素。然后将除最后一个元素的数组一分为二,满足左边数组的所有元素的值均小于最后一个元素的值,右边数组的所有元素的值均大于最后一个元素的值。如果不满足这种情况,说明这个数组一定不可能是搜索二叉树后序遍历的结果。将数组分为左边数组和右边数组,相当于将二叉树分出了左子树和右子树,然后再递归的进行如上判断即可。
public boolean isPostArray(int[] arr) {
if (arr == null || arr.length == 0) {
return false;
}
return isPost(arr, 0, arr.length - 1);
}
public boolean isPost(int[] arr, int start, int end) {
if (start == end) {
return true;
}
int less = -1;
int more = end;
for (int i = start; i < end; i++) {
if (arr[end] > arr[i]) {
less = i;
} else {
more = more == end ? i : more;
}
}
if (less == -1 || more == end) {
return isPost(arr, start, end - 1);
}
if (less != more - 1) {
return false;
}
return isPost(arr, start, less) && isPost(arr, more, end - 1);
}
学习一下题解代码的写法,通过less和more的值来判断左右子树都有or左右子树缺一个(less==-1 || more==end)。
进阶问题的分析与原问题同理,整个数组的最后一个值为二叉树头节点的值,左部分都比头节点的值小,用来生成头节点的左子树,右部分则为其右子树,通过递归生成整个二叉树。
public Node posArrayToBST(int[] posArr) {
if (posArr == null) {
return null;
}
return posToBST(posArr, 0, posArr.length - 1);
}
public Node posToBST(int[] posArr, int start, int end) {
if (start > end) {
return null;
}
Node head = new Node(posArr[end]);
int less = -1;
int more = end;
for (int i = start; i < end; i++) {
if (posArr[end] > posArr[i]) {
less = i;
} else {
more = more == end ? i : more;
}
}
head.left = posToBST(posArr, start, less);
head.right = posToBST(posArr, more, end - 1);
return head;
}
另外需要注意的是,题解的代码中自始至终都只用到了一个数组,递归传递的是索引值。而我自己写的代码中使用了Arrays.copyOfRange()方法,造了很多个数组,多余的空间有点浪费。。所以能省则省

浙公网安备 33010602011771号