题目描述
对于一个没有重复元素的整数数组,请用其中元素构造一棵MaxTree,MaxTree定义为一棵二叉树,其中的节点与数组元素一一对应,同时对于MaxTree的每棵子树,它的根的元素值为子树的最大值。现有一建树方法,对于数组中的每个元素,其在树中的父亲为数组中它左边比它大的第一个数和右边比它大的第一个数中更小的一个。若两边都不存在比它大的数,那么它就是树根。请证明这个方法的正确性,同时设计O(n)的算法实现这个方法。
给定一个无重复元素的数组A和它的大小n,请返回一个数组,其中每个元素为原数组中对应位置元素在树中的父亲节点的编号,若为根则值为-1。
测试样例:
[3,1,4,2],4
返回:[2,0,-1,2]
对这样一道题,我看到的第一时间想的就是简单嘛,不就是找这个数左边的第一个比他大的值和右边的第一个比他大的值,然后比较这两个数,取其中比较小的数填入其中不就好了。但是后面看看题目有要求要以O(n)来实现这个算法。于是上面的方法就不能用了,因为在极端情况下上面的方法会达到O(n^2)。于是我就去网上查了资料。知道了可以用stack来解决这个问题。
import java.util.*;
public class MaxTree {
public int[] buildMaxTree(int[] A, int n) {
// write code here
int res[] = new int[n];//用来存放返回数组
Stack<Integer> s = new Stack<>();//存放A中数的数组下标
for(int i = 0;i<n;i++)//遍历数组
{
int pos = -1;//默认为最大值
/**
*当stack不为空时,且stack中的栈顶元素比当前元素小时
*把栈顶元素出栈,让栈中元素保持递减原则
*看出栈元素的res[]是不是根(-1)或者是不是比A[i]大
*如果比A[i]大或是-1,那么栈顶位置所在的元素要更新成
*后面的A[i]的位置
*/
while( !s.empty() && A[s.peek()] < A[i] )
{
int t = s.peek();
s.pop();
if( res[t] == -1 || A[res[t]] > A[i] )
res[t] = i;
}
/**
*栈顶位置的元素是当前元素左边较大的第一个元素
*默认为A[i]的父节点。
*/
if(!s.empty())
pos = s.peek();
//跟新stack和res数组
s.push(i);
res[i] = pos;
}
return res;
}
}