package com.my.util;
public class Node {
public int value;
public Node left;
public Node right;
public Node(int value) {
this.value = value;
}
}
package com.my.suanfa;
import java.util.HashMap;
import java.util.Stack;
import com.my.util.Node;
/*
* 构造数组的MaxTree
* */
public class Solution04 {
public Node getMaxTree(int[] arr) {
//定义一个数组,每个元素的数据类型是一个结点类型,用来保存数组中的数字和记录该数字的左孩子和右孩子
Node[] nArr = new Node[arr.length];
//定义一个栈用来找到数组中的每个元素左边第一个比它大的元素和右边第一个比他大的元素
Stack<Node> stack = new Stack<Node>();
//定义两个map集合,lBigMap,键为该元素,值为该元素左边第一个比它大的元素,rBigMap,键为该元素,值为该元素右边第一个比他大的元素
HashMap<Node, Node> lBigMap = new HashMap<Node, Node>();
HashMap<Node, Node> rBigMap = new HashMap<Node, Node>();
//获取左边第一个比该元素大的元素
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);
}
//以上只在map中记录了出栈的元素,而栈中的元素还并没有记录进map,因此将栈中剩余元素记录进map
while(!stack.isEmpty()) {
popStackSetMap(stack,lBigMap);
}
//获取右边第一个比该元素大的元素
for(int i = nArr.length - 1; i >= 0; i--) {
Node curNode = nArr[i];
while(!stack.isEmpty() && stack.peek().value < curNode.value) {
popStackSetMap(stack, rBigMap);
}
//否则直接入栈
stack.push(curNode);
}
//将栈中剩余元素记录进map
while(!stack.isEmpty()) {
popStackSetMap(stack, rBigMap);
}
//定义方法获取每个节点的左孩子和右孩子,和父节点,连接成一棵二叉树,返回树的根结点
//定义一个头结点
Node head = null;
for(int i = 0; i < nArr.length; i++) {
//以curNode为出发点,找他的左右子节点和父节点,最终链成一棵树
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 void popStackSetMap(Stack<Node> stack, HashMap<Node, Node> map) {
Node curNode = stack.pop();
if(stack.isEmpty()) {
map.put(curNode, null);
}else {
map.put(curNode, stack.peek());
}
}
}