LeetCode654. 最大二叉树

654. 最大二叉树

文章目录

      • [654. 最大二叉树](https://leetcode.cn/problems/maximum-binary-tree/)
        • 一、题目
        • 二、题解
          • 递归解法一:
          • 递归解法二:


一、题目

给定一个不重复的整数数组 nums最大二叉树 可以用下面的算法从 nums 递归地构建:

  1. 创建一个根节点,其值为 nums 中的最大值。
  2. 递归地在最大值 左边子数组前缀上 构建左子树。
  3. 递归地在最大值 右边子数组后缀上 构建右子树。

返回 nums 构建的 *最大二叉树*

示例 1:

LeetCode654. 最大二叉树_第1张图片

输入:nums = [3,2,1,6,0,5]
输出:[6,3,5,null,2,0,null,null,1]
解释:递归调用如下所示:
- [3,2,1,6,0,5] 中的最大值是 6 ,左边部分是 [3,2,1] ,右边部分是 [0,5] 。
    - [3,2,1] 中的最大值是 3 ,左边部分是 [] ,右边部分是 [2,1] 。
        - 空数组,无子节点。
        - [2,1] 中的最大值是 2 ,左边部分是 [] ,右边部分是 [1] 。
            - 空数组,无子节点。
            - 只有一个元素,所以子节点是一个值为 1 的节点。
    - [0,5] 中的最大值是 5 ,左边部分是 [0] ,右边部分是 [] 。
        - 只有一个元素,所以子节点是一个值为 0 的节点。
        - 空数组,无子节点。

示例 2:

LeetCode654. 最大二叉树_第2张图片

输入:nums = [3,2,1]
输出:[3,null,2,null,1]

提示:

  • 1 <= nums.length <= 1000
  • 0 <= nums[i] <= 1000
  • nums 中的所有整数 互不相同

二、题解

递归解法一:

算法思路

  1. 我们首先需要找到数组中的最大值,将它作为当前树的根节点。
  2. 将数组分成两部分,左半部分包含最大值左边的元素,右半部分包含最大值右边的元素。
  3. 递归地对左半部分和右半部分进行构建,分别生成左子树和右子树。

具体实现

  1. 首先,我们需要判断数组是否为空。如果为空,直接返回空指针,表示空树。
  2. 否则,我们找到数组中的最大值和对应的下标,创建一个根节点,将最大值赋给根节点的值。
  3. 然后,我们将数组分成左右两部分,左半部分即为从数组开头到最大值的前一个元素,右半部分即为从最大值的后一个元素到数组末尾。
  4. 分别对左右两部分递归调用 constructMaximumBinaryTree 函数,得到左子树和右子树。
  5. 将左右子树连接到根节点的 leftright 成员上。
  6. 返回根节点。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        // 如果数组为空,返回空指针,表示空树
        if(nums.size() == 0) return nullptr;

        // 找到数组中的最大值和对应的下标
        vector<int>::iterator maxElement = max_element(nums.begin(),nums.end());
        int maxIndex = distance(nums.begin(),maxElement);

        // 创建根节点,将最大值赋给根节点的值
        TreeNode *root = new TreeNode();
        root->val = nums[maxIndex];

        // 将数组划分成左半部分和右半部分
        vector<int> leftMax(nums.begin(),nums.begin()+maxIndex);
        vector<int> rightMax(nums.begin()+maxIndex+1,nums.end());

        // 递归调用构建左子树和右子树
        root->left = constructMaximumBinaryTree(leftMax);
        root->right = constructMaximumBinaryTree(rightMax);

        // 返回根节点
        return root;
    }
};

算法分析

  • 时间复杂度:在每一层递归中,我们都需要找到数组中的最大值,这需要 O(n) 的时间复杂度。而每一层递归都会将数组划分成两部分,总共递归层数为树的高度,所以总体时间复杂度为 O(n^2),其中 n 是数组的长度。
  • 空间复杂度:每次递归都需要创建新的子数组,空间复杂度为 O(n)。递归调用栈的最大深度为树的高度,所以总体空间复杂度为 O(n)。
递归解法二:

算法思路:

  • 我们从整个数组中找到最大值,将其放在树的根节点上。
  • 然后,我们将数组分成两部分:左半部分和右半部分。
  • 左半部分包含最大值左边的数字,右半部分包含最大值右边的数字。
  • 接着,我们对左半部分和右半部分递归地重复上述过程,以构建左子树和右子树。

具体步骤:

  1. 创建一个私有的辅助函数 traversal,它会在一个指定的区间内构建一棵子树。
  2. 在给定的区间内,找到最大值及其下标,将最大值创建为当前子树的根节点。
  3. 将区间分成两部分:左半部分和右半部分。左半部分范围是 [left, maxValueIndex),右半部分范围是 [maxValueIndex + 1, right)
  4. 递归地对左半部分和右半部分调用 traversal 函数,得到左子树和右子树。
  5. 将左子树连接到当前根节点的左子节点,将右子树连接到当前根节点的右子节点。
  6. 返回构建好的根节点。
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    // 在左闭右开区间[left, right) 内,构造最大二叉树
    TreeNode* traversal(vector<int>& nums, int left, int right) {
        // 如果区间为空,返回空指针,表示空树
        if (left >= right) return nullptr;

        // 找到区间内的最大值下标
        int maxValueIndex = left;
        for (int i = left + 1; i < right; ++i) {
            if (nums[i] > nums[maxValueIndex]) maxValueIndex = i;
        }

        // 创建当前子树的根节点,值为区间内的最大值
        TreeNode* root = new TreeNode(nums[maxValueIndex]);

        // 递归构建左子树,区间为 [left, maxValueIndex),左闭右开
        root->left = traversal(nums, left, maxValueIndex);

        // 递归构建右子树,区间为 [maxValueIndex + 1, right),左闭右开
        root->right = traversal(nums, maxValueIndex + 1, right);

        return root;
    }
public:
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        // 调用递归函数,构建整个最大二叉树
        return traversal(nums, 0, nums.size());
    }
};

你可能感兴趣的:(LeetCode刷题,算法,LeetCode,二叉树,数据结构)