已知一个搜索二叉树后序遍历的数组posArr,根据posArr重建树
/**
* 已知一个搜索二叉树后序遍历的数组,建对应树并返回头结点
*
* 8
* / \
* 4 10
* / \ / \
* 2 6 9 12
*
* 后续遍历结果:[2,6,4,9,12,10,8]
*
*
* 思路:
* 1.后序遍历的最后一个数绝对是根节点
* 2.找左子数:从[left,right-1]范围开始找比最后一个数字小的数的最右面的那个数,记录该数字的下标为M
* 比如这里的arr[M] = 4
* 3.找右子树:从[M+1,right-1]范围找比根节点大的最后一个数,实际上就是arr[right-1]
* 4.继续递归进行
*/
public class MyPostTree {
public static void main(String[] args) {
//打印搜索二叉树
int[] arr = {2,6,4,9,12,10,8};
printTree(posArrayToBST(arr));
}
static class Node{
private int val;
private Node left;
private Node right;
public Node(int val){
this.val = val;
}
}
/**
* 构建树,O(N^2)
* @param arr
* @param left
* @param right
* @return
*/
public static Node postTree(int[] arr,int left,int right){
if (left > right){
return null;
}
Node node = new Node(arr[right]);
if (left == right){
return node;
}
//处理极端情况
int m = left - 1;
for (int i = left;i<right;i++){
if (arr[i] < arr[right]){
m = i;
}
}
// 情况一:如果只有左子树,比如 arr[1,2,3,4,5,6],即都是比最后一个数小
// node.right分支就会出现 left > right场景,即传入的是(arr,right,right-1),正好使得右节点为null;
//
// 情况二:如果只有右子树,比如 arr[6,5,4,3,2,1],即都是比最后一个数大
// 此时 m =left-1, head.left分支就会出现 left > right场景,所以 m 赋值为left-1恰到好处;
node.left = postTree(arr,left,m);
node.right = postTree(arr,m+1,right-1);
return node;
}
/**
* 优化构建树:不使用遍历查找m,使用二分查找 O(N*log2N)
* @param arr
* @param left
* @param right
* @return
*/
public static Node postTreeV2(int[] arr,int left,int right){
if (left > right){
return null;
}
Node node = new Node(arr[right]);
if (left == right){
return node;
}
//处理极端情况
int m = left - 1;
int L = left;
int R = right-1;
while (L <= R){
int mid = L + ((R - L) >> 1);
if (arr[mid] < arr[right]){
m = mid;
//mid 左侧不要,右侧继续二分
L = mid + 1;
}else{
//mid 右侧不要,左侧二分继续
R = mid - 1;
}
}
node.left = postTree(arr,left,m);
node.right = postTree(arr,m+1,right-1);
return node;
}
//**********************************************************************
//构建搜索二叉树
public static Node posArrayToBST(int[] posArr) {
if (posArr == null) {
return null;
}
return postTree(posArr, 0, posArr.length - 1);
//postTreeV2(posArr, 0, posArr.length - 1)
}
// 先序遍历打印二叉树
public static void printTree(Node head) {
System.out.println("Binary Tree:");
printInOrder(head, 0, "H", 17);
System.out.println();
}
public static void printInOrder(Node head, int height, String to, int len)
{
if (head == null) {
return;
}
printInOrder(head.right, height + 1, "v", len);
String val = to + head.val + to;
int lenM = val.length();
int lenL = (len - lenM) / 2;
int lenR = len - lenM - lenL;
val = getSpace(lenL) + val + getSpace(lenR);
System.out.println(getSpace(height * len) + val);
printInOrder(head.left, height + 1, "^", len);
}
public static String getSpace(int num) {
String space = " ";
StringBuffer buf = new StringBuffer("");
for (int i = 0; i < num; i++) {
buf.append(space);
}
return buf.toString();
}
}
运行结果: