题目来源:. - 力扣(LeetCode)
题目思路分析
题目描述
给定一个无序的整数数组,你需要构建一棵最大二叉树。在这棵二叉树中,每个节点的值都大于其子树中所有其他节点的值。换句话说,每个节点都是其子树中的最大值节点。根据这个定义,我们需要编写一个函数来构建这样的二叉树。
思路分析
-
方法一:单调栈
- 使用一个栈来存储数组元素的索引,栈中的索引对应的元素值是单调递减的。
- 遍历数组,对于每个元素,如果栈不为空且当前元素大于栈顶索引对应的元素值,则不断弹出栈顶元素,并将弹出的元素作为当前元素的左子节点。
- 弹出结束后,如果栈不为空,则栈顶元素对应的节点为当前元素的右子节点的父节点(或祖父节点等,取决于之前弹出的元素数量)。
- 将当前元素的索引压入栈中。
- 最后,栈中剩余的索引对应的节点中,栈底的索引对应的节点即为整棵树的根节点。
-
方法二:递归
- 递归地找到子数组中的最大值及其索引。
- 以最大值为根节点创建一个新的树节点。
- 递归地构建左子树和右子树,左子树由最大值左侧的子数组构建,右子树由最大值右侧的子数组构建。
- 返回构建好的节点。
代码:
方法一:单调栈
class Solution {
public: TreeNode* constructMaximumBinaryTree(vector<int>& nums) { int n = nums.size(); vector<int> value; // 用于存储数组元素的索引,保持栈中索引对应的元素值单调递减 vector<TreeNode*> tree(n); // 用于存储每个索引对应的树节点 for (int i = 0; i < n; ++i) { tree[i] = new TreeNode(nums[i]); // 为当前元素创建一个新的树节点 // 当栈不为空且当前元素大于栈顶索引对应的元素值时,处理左子树 while (!value.empty() && nums[i] > nums[value.back()]) { tree[i]->left = tree[value.back()]; // 将弹出的索引对应的节点作为当前节点的左子节点 value.pop_back(); // 弹出栈顶索引 } // 如果栈不为空,则栈顶索引对应的节点为当前节点的右子节点的父节点(或更上层的节点) // 但由于我们是从左到右遍历的,所以这里只需要将当前节点设置为栈顶索引对应节点的右子节点即可 // 之前的左子树构建已经确保了正确的父子关系 if (!value.empty()) { tree[value.back()]->right = tree[i]; } value.push_back(i); // 将当前索引压入栈中 } // 栈底索引对应的节点即为整棵树的根节点 return tree[value[0]]; }
};
方法二:递归
class Solution {
public: // 递归函数,用于构建最大二叉树 TreeNode* construct(const vector<int>& nums, int begin, int end) { // 递归终止条件:子数组为空 if (begin > end) { return nullptr; } // 找到子数组中的最大值及其索引 int max = begin; for (int i = begin + 1; i <= end; ++i) { if (nums[i] > nums[max]) { max = i; } } // 以最大值为根节点创建一个新的树节点 TreeNode* node = new TreeNode(nums[max]); // 递归构建左子树和右子树 node->left = construct(nums, begin, max - 1); node->right = construct(nums, max + 1, end); // 返回构建好的节点 return node; } // 主函数,调用递归函数构建最大二叉树 TreeNode* constructMaximumBinaryTree(vector<int>& nums) { return construct(nums, 0, nums.size() - 1); }
};
知识点摘要
- 单调栈:用于解决一些与数组元素顺序相关的问题,通过维护一个单调的栈来优化算法。
- 递归:一种在函数内部调用自身的方法,常用于解决可分解为相似子问题的问题。
- 二叉树:一种数据结构,其中每个节点最多有两个子节点,称为左子节点和右子节点。
本文介绍了两种从无序整数数组构建最大二叉树的方法:单调栈和递归。单调栈方法通过维护一个单调递减的栈来构建二叉树,而递归方法则通过递归地找到子数组中的最大值来构建二叉树。两种方法各有优缺点,单调栈方法在某些情况下可能更高效,而递归方法则更直观易懂。无论使用哪种方法,都需要对二叉树的基本结构和操作方法有深入的理解。通过这两种方法的比较和学习,我们可以更好地理解数据结构中的算法设计和优化。