要求:给定一个无序的,无重复元素的数组,生成MaxTree,要求每一个根节点处为当前最大值
时间复杂度要求O(n),空间复杂度O(n)
思路:一开始第一个想法是排序,在生成二叉排序树之类的,堆排序递归之类的,但是题目要求了时间复杂度为O(n),这些方 法都超了。但是题目没有要求生成的MaxTree一定为完全二叉树之类的,只要符合根节点最大,所以,我们可以自己规定MaxTree的特点。(书上P23页开始),证明了除全局最大的根节点有两个子树,其他根节点全是单边的。最后生成的树感觉是只有两条腿。。。。。
e.g.[3,4,5,1,2]
5
/ \
4 2
/ /
3 1
这样就会出现一个规则,一个节点的位置与它在数组中左右相邻的最大值有关。具体见书23页。。。。
※※※ 关于记录两边的相邻最大值。可以用stack结构辅助。例如【3,1,2】,首先压入3,再看1,比3小,继续压入。再看2,比1大,说明2的左侧相邻最大值在1的下面,首先记录map(1,3),说明1的左侧最大值确定了是3,记录好之后弹出1,剩下3,3比2大,OK,直接压入2。 最后栈中的顺序为【3,2】,再依次pop出来,生成map对。
public TreeNode getMaxTree(int[] arr) {
TreeNode[] narr = new TreeNode[arr.length];
for(int i=0; i<arr.length;i++) {
narr[i] = new TreeNode(arr[i]);
}
Stack<TreeNode> stack = new Stack<TreeNode>(); //用stack栈结构来寻找相邻的最大值。
HashMap<TreeNode,TreeNode> left = new HashMap<TreeNode,TreeNode>(); //用两个map来分别存储每一个节点的左大,右大
HashMap<TreeNode,TreeNode> right = new HashMap<TreeNode,TreeNode>(); //注意存的都为节点本身,没有比他大的酒味null
//////////////////记左边最大/////////////////////
for(int i=0;i!=narr.length;i++) { //先从左到右记一遍,左侧相邻最大的,生成一个leftMap
TreeNode cur = narr[i];
while(!stack.isEmpty()&&stack.peek().value<cur.value) { //若此时的值比栈顶大,首先记录栈顶元素下面的最大值,再弹出它,把当前值压入。
popStackSetMap(stack,left); //中间逆序的单独记
}
stack.push(cur); //正常的顺序直接压进去
}
while(!stack.isEmpty()) { //最后再记一遍顺序正确的
popStackSetMap(stack,left);
}
////////////////////记右边最大/////////////////
for(int i = narr.length;i>=0;i--) { //再从右到左记一遍,记右侧相邻大的,生成一个rightMap
TreeNode cur = narr[i];
while(!stack.isEmpty()&&stack.peek().value<cur.value) {
popStackSetMap(stack,right); //中间逆序单独计
}
stack.push(cur); //正常的顺序直接压进去
}
while(!stack.isEmpty()) {
popStackSetMap(stack,right); //最后再记一遍顺序正确的元素
}
/////////////////开始生成树//////////////////
TreeNode head = null;
for(int i=0;i<narr.length;i++) {
TreeNode cur = narr[i]; //分别取出当前节点的左,右最大值(存的是节点)
TreeNode leftNode = left.get(cur);
TreeNode rightNode = right.get(cur);
//根据左右最大值的情况来进行判断
if(left==null&&right==null) { //若左,右都没有比它还大的,那么它就是最大值,为根节点
head = cur;
}else if(leftNode==null){ //只有右侧有 4
if(rightNode.left==null) {
rightNode = cur;
}else {
rightNode.right = cur;
}
}else if(right==null) { //只有左侧有 2
if(leftNode.left==null) {
leftNode.left = cur;
}else {
leftNode.right = cur;
}
}else { //两侧都有 1
TreeNode parent = leftNode.value<right.value?leftNode:rightNode;
if(parent.left==null) {
parent.left = cur;
}else {
parent.right = cur;
}
}
}
return head;
}
public void popStackSetMap(Stack<TreeNode> stack,HashMap<TreeNode,TreeNode> map) {
TreeNode popNode = stack.pop(); //弹出元素
if(stack.isEmpty()) { //生成map的函数
map.put(popNode, null);
}else {
map.put(popNode, stack.peek());
}
}