日月的弯刀  
Where Amazing Happens!

转载请标明出处http://www.cnblogs.com/haozhengfei/p/2490d09c73b23343eaa5ccaa090bf409.html 


数组变树练习题

 
数组变树练习
 

第9节 数组变树练习题

对于一个没有重复元素的整数数组,请用其中元素构造一棵MaxTree,MaxTree定义为一棵二叉树,其中的节点与数组元素一一对应,同时对于MaxTree的每棵子树,它的根的元素值为子树的最大值。现有一建树方法,对于数组中的每个元素,其在树中的父亲为数组中它左边比它大的第一个数和右边比它大的第一个数中更小的一个。若两边都不存在比它大的数,那么它就是树根。请设计O(n)的算法实现这个方法。

给定一个无重复元素的数组A和它的大小n,请返回一个数组,其中每个元素为原数组中对应位置元素在树中的父亲节点的编号,若为根则值为-1。

测试样例:
[3,1,4,2],4
返回:[2,0,-1,2]
 
 
1
import java.util.*;
2

3
public class MaxTree {
4
    public int[] buildMaxTree(int[] A, int n) {
5
        if(A == null || n == 0) 
6
            return null;
7
        int[] result = new int[n];
8
        Stack<Integer> stack = new Stack<>();
9

10
        //初始状态下,所有元素的父结点都为 null,对应下标为-1
11
        Arrays.fill(result,-1);
12

13
     // 循环处理每一个元素
14
        // 需要一个额外的栈来辅助获取两个阶段的最大值(两个阶段指左边最大值和右边最大值)
15
        // 每次判断一个元素分三种情况
16
        //  1. 栈为空,也就是初始状态,直接将元素下标入栈(此时该元素的父结点下标为默认值 -1)
17
        //  2. 栈不为空,同时即将进栈的元素比栈顶元素小,那么直接将元素进栈同时更新当前元素的
18
        //     父结点下标为i(设定父结点为左边第一个比该元素大的,右侧第一个比该元素大的第3步说明)
19
        //  3. 栈不为空,同时即将进栈的元素比栈顶元素大,那么需要将栈顶元素出栈,然后比较
20
        //     需要分情况:
21
        //     1) 栈顶元素对应父结点下标为null, 说明栈顶元素左侧没有最大值,此时需要更新
22
        //        栈顶元素对应父结点下标为当前进栈元素的下标 i,然后将栈顶元素pop 出栈
23
        //     2) 栈顶元素对应的父结点下标对应数组中元素比,i 位置对应数组元素大,由maxTree 的
24
        //        定义,我们必须保存左侧和右侧相对较小的那个作为最终结果,所以也更新元素下标为i
25
        //        然后将栈顶元素 pop 出栈
26
        //     3) 如果不在上面两种情况范围内,直接将栈顶元素出栈,然后继续循环执行 3 步骤
27
        for(int i=0;i<n;i++){
28
            // 比较复杂的核心操作
29
            while(!stack.isEmpty() && A[stack.peek()]<A[i]){
30
                // 如果即将《被pop 元素》的左侧最大值为null 或者其左侧最大值比右侧(A[i])最大值大
31
                // 需要先更新该元素的父结点为右侧结点下标
32
                if(result[stack.peek()] == -1 || A[result[stack.peek()]]>A[i]){
33
                    result[stack.peek()] = i;//更新成右侧最大值
34
                }
35

36
                // 不管更新没更新栈顶元素最终的父结点下标,接下来都需要把其pop 出栈
37
                stack.pop();
38
            }
39

40
            // 经过上面循环,判断一下栈是否为空了
41
            if(!stack.isEmpty()){
42
                //如果不空,更新当前元素左侧第一个比它大的父结点为栈顶元素
43
                result[i] = stack.peek();
44
            }
45
            //不管栈是否为空,最终都要将当前元素进栈
46
            stack.push(i);
47
        }
48
        return result;
49
    }
50
}
 
 
您的代码已保存
答案正确:恭喜!您提交的程序通过了所有的测试用例
 
posted on 2017-03-19 13:28  日月的弯刀  阅读(1934)  评论(0编辑  收藏  举报