轉載請標明出處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
}
您的代碼已保存
答案正確:恭喜!您提交的程序通過了所有的測試用例
答案正確:恭喜!您提交的程序通過了所有的測試用例