【题目】定义二叉树节点如下:
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int value) {
this.value = value;
}
}
一个数组的MaxTree定义如下。
- 数组必须没有重复元素。
- MaxTree是一棵二叉树,数组的每一个值对应一个二叉树节点。
- 包括MaxTree树在内且在其中的每一棵子树上,值最大的节点都是树的头。
【要求】给定一个没有重复元素的数组arr,写出生成这个数组的MaxTree的函数,要求如果数组长度为N,则时间复杂度为O(N)、额外空间复杂度为O(N)。
思路:以下列原则来建立这棵树:
-
每一个数的父节点是它左边第一个比它的数和它右边第一个比它大的数中,较小的那个。
-
如果一个数左边没有比它大的数,右边也没有。也就是说,这个数是整个数组的最大值,那么这个数是MaxTree的头节点。
找每个数左边第一个比它大的数,从左到右遍历每个数,栈中保持递减序列,新来的数不停地利用Pop出栈顶,直到栈顶比新数大或没有数。相同的方法确定右边比它大的第一个数。
public class MaxTree {
public static class Node {
public int value;
public Node left;
public Node right;
public Node(int value) {
this.value = value;
}
}
public static Node getMaxTreeTree(int[] arr) {
Node[] nArr = new Node[arr.length];
for (int i = 0; i < arr.length; i++) {
nArr[i] = new Node(arr[i]);
}
Stack<Node> stack = new Stack<>();
HashMap<Node, Node> lBigMap = new HashMap<>();
HashMap<Node, Node> rBigMap = new HashMap<>();
for (int i = 0; i < nArr.length; i++) {
while (!stack.isEmpty() && stack.peek().value < nArr[i].value) {
popStackSetMap(stack, lBigMap);
}
stack.push(nArr[i]);
}
while (!stack.isEmpty()) {
popStackSetMap(stack, lBigMap);
}
for (int i = nArr.length - 1; i > 0; i--) {
while (!stack.isEmpty() && stack.peek().value < nArr[i].value) {
popStackSetMap(stack, rBigMap);
}
stack.push(nArr[i]);
}
while (!stack.isEmpty()) {
popStackSetMap(stack, rBigMap);
}
Node head = null;
for (int i = 0; i < nArr.length; i++) {
Node curNode = nArr[i];
Node left = lBigMap.get(curNode);
Node right = rBigMap.get(curNode);
if (left == null && right == null) {
head = curNode;
} else if (left == null) {
if (right.left == null) {
right.left = curNode;
} else {
right.right = curNode;
}
} else if (right == null) {
if (left.left == null) {
left.left = curNode;
} else {
left.right = curNode;
}
} else {
Node parent = left.value > right.value ? left : right;
if (parent.left == null) {
parent.left = curNode;
} else {
parent.right = curNode;
}
}
}
return head;
}
public static void popStackSetMap(Stack<Node> stack, HashMap<Node, Node> map) {
Node cur = stack.pop();
if (stack.isEmpty()) {
map.put(cur, null);
} else {
map.put(cur, stack.peek());
}
}
}