题目描述
对于一个没有重复元素的整数数组,请用其中元素构造一棵MaxTree,MaxTree定义为一棵二叉树,其中的节点与数组元素一一对应,同时对于MaxTree的每棵子树,它的根的元素值为子树的最大值。现有一建树方法,对于数组中的每个元素,其在树中的父亲为数组中它左边比它大的第一个数和右边比它大的第一个http://write.blog.youkuaiyun.com/postedit?ref=toolbar&ticket=ST-3460-nsEg1YRiH0DI6jAbV4uJ-passport.youkuaiyun.com数中更小的一个。若两边都不存在比它大的数,那么它就是树根。请证明这个方法的正确性,同时设计O(n)的算法实现这个方法。
给定一个无重复元素的数组A和它的大小n,请返回一个数组,其中每个元素为原数组中对应位置元素在树中的父亲节点的编号,若为根则值为-1。
测试样例:
[3,1,4,2],4
返回:[2,0,-1,2]
思路:首先找到最大的元素,作为树根。这里构造了一个方法findTheMax来查找A数组任意指定区间内的最大值,返回其下标。然后采用分治策略分别对树根左右区间进行处理。要留意如果区间是一个开区间,即最左边是下标0或最右边是下标n-1,这时需要设置一个哨兵位来保证一个开区间内的最大值(也就是这个区间形成的子树的根)能正常找到它的父节点(即区间两端较小的那个值)。这个过程也就是填充result数组的过程,用fillTheSubtree方法操作实现。
import java.util.*;
public class MaxTree {
public static int findTheMax(int st,int ed,int[] raw){
int mj = -1;
int max = -1;
for(int i=st;i<=ed;i++){
if(raw[i]>max){
max = raw[i];
mj = i;
}
}
return mj;
}
public static void fillTheSubtree(int st,int ed,int[] raw,int[] result){
if(st>ed)
return;
int le = st-1;
int lev = 100000000;
int ri = ed+1;
int riv = 100000000;
if(le>=0){
lev = raw[le];
}
if(ri<=raw.length-1){
riv = raw[ri];
}
int dopo = findTheMax(st,ed,raw);
int less = lev>riv?ri:le;
result[dopo] = less;
fillTheSubtree(st,dopo-1,raw,result);
fillTheSubtree(dopo+1,ed,raw,result);
}
public int[] buildMaxTree(int[] A, int n) {
// write code here
int[] result = new int[n];
Arrays.fill(result, 0);
int m = findTheMax(0,n-1,A);
result[m] = -1;
fillTheSubtree(0,m-1,A,result);
fillTheSubtree(m+1,n-1,A,result);
return result;
}
}