Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

0654最大二叉树.md增加新非递归算法 #2897

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added pics/654最大二叉树.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
90 changes: 90 additions & 0 deletions problems/0654.最大二叉树.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,96 @@ root->right = traversal(nums, maxValueIndex + 1, right);

第二版相应的终止条件,是遇到空节点,也就是数组区间为0,就终止了。

### 非递归方法

将原数组转化为二叉树时,使数字飘起来,可以想象:越大的数字飘得越高(越接近根节点)。

如原题 【3,2,1,6,0,5】:

<img src="..\pics\654最大二叉树.png" alt="image-20250216223034714" style="zoom:67%;" />

以 **从左到右遍历数组** 的方式构造最大二叉树,避免了递归方法带来的额外栈空间消耗,时间效能上也优一些。

1. 首先创建一个存放各个节点的地址的vector, 可以先把各个节点创建出来,也可以在遍历的过程中创建。

2. 遍历 `nums` 逐步构造树

```cpp
for (int i = 1; i < nums.size(); i++) {
TreeNode* t = new TreeNode(nums[i]);
arr.push_back(t);
```

- 依次读取 `nums[i]` 并新建 `TreeNode`,同时存入 `arr` 数组。

3. **找到 `nums[i]` 前面第一个比它大的数`nump[j]`,则 i 对应的节点应该是 j 节点的右子树,并把 j 原来的右子树(在数组的位置是 i 左边)放在 i 的左子树上。**

```cpp
int j = i - 1;
for (; j >= 0; j--) {
if (nums[j] > nums[i]) {
TreeNode* l = arr[j]->right;
arr[j]->right = t;
t->left = l;
break;
}
}
```

- 从 `nums[i]` **向左遍历**,找到 **第一个比 `nums[i]` 大的数 `nums[j]`**。
- 构造父子关系:
- `nums[i]` 作为 `nums[j]` 的**右子节点**。
- 若 `nums[j]` 原本已有右子树 `l`,则 `l` 作为 `nums[i]` 的**左子节点**。

4. .处理 `nums[i]` 是当前最大值的情况

```cpp
if (j == -1) {
t->left = root;
root = t;
}
```

- 如果 `nums[i]` 比前面所有数都大,则为新的根节点:
- 设 `t->left = root`,即将 `root` 作为 `t` 的左子树。
- 更新 `root = t`,因为 `nums[i]` 是当前最大值,必须作为新的根节点。

代码如下:

```cpp
class Solution {
public:
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
// new一个根节点
TreeNode* root = new TreeNode(nums[0]);
// 创建一个存放各个node地址的数组,方便修改,与nums顺序一致
vector<TreeNode*> arr;
// 先把第一个节点设为根节点,放入数组
arr.push_back(root);
for(int i = 1; i < nums.size(); i++) {
TreeNode* t = new TreeNode(nums[i]);
arr.push_back(t);
int j = i-1;
for(; j >= 0; j--) {
/* 找到前面第一个大于该数的已有节点 */
if(nums[j] > nums[i]){
TreeNode* l = arr[j]->right;
arr[j]->right = t;
t->left = l;
break;
}
}
if(j == -1){
/* 若没有更大的,说明这个数是目前最大的,设为根节点 */
t->left = root;
root = t;
}
}
return root;
}
};
```

## 总结


Expand Down