题目描述
一个数组的MaxTree定义如下:
数组必须没有重复元素。
MaxTree是一棵二叉树, 数组的每一个值对应一个二叉树节点。
包括MaxTree树在内且在其中的每一棵子树上, 值最大的节点都是树的头。
给定一个没有重复元素的数组arr, 写出生成这个数组的MaxTree的函数, 要求如果数组长度为N, 则时间复杂度为O(N)、 额外空间复杂度为O(N)。
解题思路
解法一:可以利用堆,构造堆的时间复杂度是O(N)
解法二:利用单调栈求出数组中每个位置左右最近的比它大的值,然后让左右都为null的结点作为头结点,只有左边大的的作为左边结点的左孩子,只有右边结点大的作为右边结点的右孩子,左右比它大的都有的,选择两个中较小的,作为较小的结点的孩子
代码
package TestNode.StackAndQueue;
import java.util.HashMap;
import java.util.Stack;
public class MaxTree {
static class Node{
public int value;
public Node left;
public Node right;
public Node(int value) {
this.value = value;
}
}
// 方法一:通过单调栈实现
public static Node getMaxTree(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++) {
Node curNode = nArr[i];
while ((!stack.isEmpty()) && stack.peek().value < curNode.value) {
popStackSetMap(stack,lBigMap);
}
stack.push(curNode);
}
while (!stack.isEmpty()) {
popStackSetMap(stack,lBigMap);
}
for (int i = nArr.length - 1; i != -1; i--) {
Node curNode = nArr[i];
while ((!stack.isEmpty()) && stack.peek().value < curNode.value) {
popStackSetMap(stack,rBigMap);
}
stack.push(curNode);
}
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;
}
private static void popStackSetMap(Stack<Node> stack, HashMap<Node, Node> map) {
Node popNode = stack.pop();
if (stack.isEmpty()) {
map.put(popNode, null);
} else {
map.put(popNode,stack.peek());
}
}
// 方法二: 通过堆实现
public static Node getMaxTree2(int[] arr){
Node[] nArr = new Node[arr.length];
for (int i = 0; i < arr.length; i++) {
nArr[i] = new Node(arr[i]);
}
for (int i = 0; i < nArr.length; i++) {
heapfiyInsert(nArr, i);
}
for (int i = 0; i < nArr.length; i++) {
if (2*i+1 < nArr.length){
nArr[i].left = nArr[2*i+1];
}
if (2*i+2 < nArr.length){
nArr[i].right = nArr[2*i+2];
}
}
return nArr[0];
}
static void heapfiyInsert(Node[] nArr, int index){
while (nArr[index].value > nArr[(index-1)/2].value){
swap(nArr, index, (index-1)/2);
index = (index-1)/2;
}
}
static void swap(Node[] nArr, int a, int b){
Node temp = nArr[a];
nArr[a] = nArr[b];
nArr[b] = temp;
}
public static void main(String[] args) {
int[] arr = new int[]{3,4,1,2};
// getMaxTree(arr);
getMaxTree2(arr);
}
}