題目
一個數組的MaxTree定義:
- 數組必須沒有重復元素
- MaxTree是一棵二叉樹,數組的每一個值對應一個二叉樹節點
- 包括MaxTree樹在內且在其中的每一棵子樹上,值最大的節點都是樹的頭
給定一個沒有重復元素的數組arr,寫出生成這個數組的MaxTree的函數,要求如果數組長度為N,則時間負責度為O(N)、額外空間負責度為O(N)。
實現思路
對每一個元素,從左邊和右邊各選擇第一個比這個元素大的值,選擇值較小的元素作為父節點。
??在【生成窗口最大數組】里面,已經掌握了,在O(N)時間復雜度里面,找到每個元素位置最近的比元素大的元素,同個這個套路,就可以構造一棵MaxTree了。
證明
1 構造的不是森林
2 是一棵二叉樹
證明:1??
??對于每一個樹節點,都能往上找到一個節點,直到找到最大節點為止,這樣所有樹節點都有共同的父節點,這樣構造出來的就是一棵樹。
證明:2
??使用反證法解決,如果是一棵二叉樹,那么對于每個作為父節點的元素,能夠在元素的一邊找到兩個或兩個以上的元素。存在如:[p, b1, x, b2]這樣的結構,p是父節點、b1、b2為子節點, x為其他節點。
- 按照題目,可以設定:
??p > b1, p > b2 - 當b1 > b2:
??b2不會選擇p作為父節點,可能選擇b1作為父節點. - 當b1 < b2:
??當x < b2時,b1不會選擇p作為父節點,選擇b2作為父節點.
??當x > b2時,b2不會選擇p作為父節點,選擇x作為父節點.
代碼
使用套路獲取從左到右或從右到左第一個比這個元素大的值:
private List<Integer> getMaxList(List<Integer> valList, boolean reverse){
//套路
List<Integer> tMaxItemDeque = new LinkedList<>();
Stack<Integer> tStackHelper = new Stack<>();
Integer maxItem;
Iterator<Integer> iter;
if(reverse)
iter = new ReverseListIterator(valList);
else
iter = valList.iterator();
while (iter.hasNext()) {
Integer item = iter.next();
maxItem = null;
while(false == tStackHelper.isEmpty()){
Integer peekItem = tStackHelper.peek();
if(peekItem > item)
{
maxItem = peekItem;
tStackHelper.push(item);
break;
}
tStackHelper.pop();
}
if(tStackHelper.isEmpty()){
tStackHelper.push(item);
}
tMaxItemDeque.add(maxItem);
}
return tMaxItemDeque;
}