![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/a31d96a8d8d8090e2ab32022bd62e437.png)
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/f7a89d6408ecb6a5a745553edac46481.png)
1. 法一:单调栈
注意:单调栈比递归方法难理解的多,单调栈时间复杂度为O(n),递归方法的时间复杂度为O(
n
2
n^2
n2). 实际工作场景中,单调栈的效率肯定更高
,但是这是做题,因为测试用例的数量较少,反而会比下面递归方法花费的时间更多。所以不要因为提交后发现这个算法效率没有递归的高就放弃掌握此方法。
- 利用单调栈来处理
- 每一个结点都要入栈,但是入栈前:
- 如果栈中已经入栈的,都比它小,说明他就是一个中间结点,那么栈中的元素应该是他的左区间,应该成为它的左子树
- 如果栈中已经入栈的,比当前要入栈的结点node大,说明,node应该成为人家栈顶元素的右子树。
- 最终返回栈低那个最大的元素,就是构造完成的二叉树的根节点
图解如下:
- 第一个元素可以无脑入栈
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/639c98b7bd5fc72b81d1e9cddeff9b41.png)
- 第二个元素,2,入栈时发现栈顶元素3比它大,说明2应该是栈顶右子树,然后栈顶元素指向2
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/c3195f44d330ba3af99e4f0b94e5696f.png)
- 第三个元素,1,入栈时发现栈顶元素2,比它大,说明1应该是栈顶元素右子树,然后栈顶元素指向1.
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/1f275ac197c19142ab8dffbd5bad5120.png)
- 第4个元素,6
- 入栈时发现栈顶为1,比它小,则出栈1,成为其左子树
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/46ba37a5ac539d01e08c05d68bda29da.png)
- 然后发现新的栈顶2依然比它小,继续出栈成为其左子树
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/083af01be7de9c23f41f6fed6757e291.png)
- 然后发现栈顶3依然比它小,继续出栈成为其左子树,然后栈空了,将6入栈,此时栈中只有一个6结点
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/5fda437173b2379f004dce2a42f428bd.png)
- 第5个元素,0,入栈时发现比栈顶6小,成为其右子树然后入栈
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/292d77ced7d23b0b52c305dfd58c8701.png)
- 第6个元素,5
- 入栈时发现比栈顶0大,则0出栈成为其左子树
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/49db5e89d31df857e78b70501ff941fb.png)
- 然后发现,栈顶的6比它大,它就得成为6的右子树,然后入栈
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/464d9188a3944cec8d266b3c0e08e065.png)
此时,完成了遍历,二叉树也构造完成,栈中的元素为[6,5],其中5是栈顶。而栈低必然是根节点6.所以最后我们得返回栈低的6
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/0e563bb9a9f0fd0792a8a8e89f735007.png)
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
if(nums.length == 0) return null;
if(nums.length == 1) return new TreeNode(nums[0]);
int n = nums.length;
TreeNode[] stack = new TreeNode[n];
int index = -1;
for (int i = 0; i < n; ++i) {
TreeNode node = new TreeNode(nums[i]);
while (index > -1 && nums[i] > stack[index].val) {
node.left = stack[index--];
}
if (index>-1) {
stack[index].right = node;
}
stack[++index] = node;
}
return stack[0];
}
}
2. 法二:递归
解题思路:时间复杂度O(
n
2
n^2
n2),空间复杂度O(n) |
---|
- 划分区间,每次找区间最大值,然后再次以它为中心,划分两个区间
- 初始区间是整个数组,找到最大值后,以它为中心划分两个区间再次递归
- 左边区间是它的左节点,右边区间是它的右节点
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/cc612a25e8c9de11b0ed853bc267a24a.png)
class Solution {
public TreeNode constructMaximumBinaryTree(int[] nums) {
return constructMaximumBinaryTree(nums,0,nums.length-1);
}
public TreeNode constructMaximumBinaryTree(int[] nums,int left,int right) {
if(right < left) return null;
if(right == left ) return new TreeNode(nums[left]);
int maxIndex = left;
for(int i = left+1;i<=right;i++)
if(nums[i]>nums[maxIndex]) maxIndex = i;
TreeNode node = new TreeNode(nums[maxIndex]);
node.left = constructMaximumBinaryTree(nums,left,maxIndex-1);
node.right = constructMaximumBinaryTree(nums,maxIndex+1,right);
return node;
}
}