LeetCode-654. Maximum Binary Tree

本文探讨了在LeetCode上解决构建最大二叉树问题的两种方法:一种是正向思维的递归方法,效率较低;另一种是利用栈进行一次遍历的高效算法,通过维护一个降序栈来构建树,避免了递归的开销。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在leetcode,觉得不刷题的话,思维能力会下降。

题目:

Given an integer array with no duplicates. A maximum tree building on this array is defined as follow:

The root is the maximum number in the array.
The left subtree is the maximum tree constructed from left part subarray divided by the maximum number.
The right subtree is the maximum tree constructed from right part subarray divided by the maximum number.
Construct the maximum tree by the given array and output the root node of this tree.

Example 1:
Input: [3,2,1,6,0,5]
Output: return the tree root node representing the following tree:

      6
    /   \
   3     5
    \    / 
     2  0   
       \
        1
Note:
The size of the given array will be in the range [1,1000].

题目的大意是数组中的最大的数是树的根节点,最大数的左边是该根节点的左子树,右边是该根节点的右子树,最大的数的左右边的数组同样的规则形成各自的子树。

1.自己写的:正向思维,按照正常思路写递归;效率比较低,代码如下:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
//    Runtime: 108 ms, faster than 26.14% of C++ online submissions for Maximum Binary Tree.
//    Memory Usage: 38.1 MB, less than 24.71% of C++ online submissions for Maximum Binary Tree.
    TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
        if(nums.size() == 0)
            return nullptr;
        vector<int>::iterator it = std::max_element(nums.begin(), nums.end());
        int index = it - nums.begin();
        int max = *it;

        TreeNode *node = new TreeNode(max);
        vector<int> vecLeft;
        if(index > 0)
            vecLeft = vector<int>(nums.begin(), nums.begin() + index);
        node->left = constructMaximumBinaryTree(vecLeft);

        vector<int> vecRight;
        if(index < nums.size())
            vecRight = vector<int>(nums.begin() + index + 1, nums.end());
        node->right = constructMaximumBinaryTree(vecRight);
        return node;
    }
};

2.评论中别人写的:

思路:[3,2,1,6,0,5]从左到右遍历数组,时间O(n),相当于从左到右建立树,开始建立已遍历数组的子树的条件是出现一个数比前一个数大,因此栈保存的永远是降序的数组,由于从左开始
1.左边>当前,左边的数比当前大,则当前数不会有左子树,当前->left = null,当前进栈
2.左边<当前,最大值出现,形成左子树,由于栈是降序数组,所以依次出栈,直到当前值小于栈中的值,并且->right = nullptr,栈底值为当前的左子树根,当前进栈

//    Runtime: 72 ms, faster than 97.18% of C++ online submissions for Maximum Binary Tree.
//    Memory Usage: 26.3 MB, less than 99.43% of C++ online submissions for Maximum Binary Tree.
    TreeNode* constructMaximumBinaryTree_(vector<int> &nums)
    {
        stack<TreeNode*> s;
        const auto up = [&](int x) {
            TreeNode* child = nullptr;
            while (!s.empty() && (s.top()->val <= x)) {
                s.top()->right = child;
                child = s.top();
                s.pop();
            }
            return child;
        };
        for (const auto x : nums) {
            const auto node = new TreeNode(x);
            node->left = up(x);
            s.push(node);
        }
        return up(numeric_limits<int>::max());
    }

一次遍历就解决了惯性思维中的递归,一个很好的思路。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值