构造MaxTree

题目描述



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

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



测试样例:

[3,1,4,2],4
返回:[2,0,-1,2]


 


 



算法的证明左神的书中解释的很详细,大致:


1. 该方法可以生成一棵树 不会是森林(所有元素都不同 向上总会有一个共同的最大值)


2. 该方法,所有元素最多只有两个孩子。(只需证明每个数一侧只会最多有一个孩子)



关于算法的复杂度:时间O(n) 空间O(n)


C++代码如下:




 



1


2


3


4


5


6


7


8


9


10


11


12


13


14


15


16


17


18


19


20


21


22


23


24


25


26


27


28


29




​vector<​​​​int​​​​> buildMaxTree(vector<​​​​int​​​​> A, ​​​​int​​ ​​n) {​


​if​​ ​​(n <= 0){​


​return​​ ​​vector<​​​​int​​​​>();​


​}​


​vector<​​​​int​​​​> res;  ​​​​// 数组元素在树中父亲节点的编号​


​stack<​​​​int​​​​> s;     ​​​​// 栈 以递减方式存放元素值的位置index​


 


​for​​ ​​(​​​​int​​ ​​i = 0; i < n; ++i){​


​int​​ ​​pos = -1; ​​​​// 根编号为-1​


 


​// 当前访问的元素比栈顶大 栈中元素需要出栈​


​while​​​​(!s.empty() && A[i] > A[s.top()]){​


​int​​ ​​tmp = s.top();s.pop();​


 


​if​​ ​​(res[tmp] == -1 || A[i] < A[res[tmp]]){​


​res[tmp] = i;​


​}​


​}​


​// 找到了最近的比A[i]大的数​


​if​​ ​​(!s.empty()){​


​pos = s.top();​


​}​


 


​s.push(i);​


​res.push_back(pos);​


​}​


 


​return​​ ​​res;​


​}​