首页 > 其他分享 >[LeetCode] 1339. Maximum Product of Splitted Binary Tree 分裂二叉树的最大乘积

[LeetCode] 1339. Maximum Product of Splitted Binary Tree 分裂二叉树的最大乘积

时间:2023-04-05 13:56:51浏览次数:54  
标签:node Binary Product cur res sum 结点 dfs 二叉树


Given the root of a binary tree, split the binary tree into two subtrees by removing one edge such that the product of the sums of the subtrees is maximized.

Return the maximum product of the sums of the two subtrees. Since the answer may be too large, return it modulo 109 + 7.

Note that you need to maximize the answer before taking the mod and not after taking it.

Example 1:

Input: root = [1,2,3,4,5,6]
Output: 110
Explanation: Remove the red edge and get 2 binary trees with sum 11 and 10. Their product is 110 (11*10)

Example 2:

Input: root = [1,null,2,3,4,null,null,5,6]
Output: 90
Explanation: Remove the red edge and get 2 binary trees with sum 15 and 6.Their product is 90 (15*6)

Constraints:

  • The number of nodes in the tree is in the range [2, 5 * 104].
  • 1 <= Node.val <= 104

这道题给了一棵二叉树,说是可以移除任意一条边,将其分成两棵子树,需要将二棵子树的结点值分别都加起来,然后相乘,让返回可能最大的乘数,并对一个超大数取余。首先来分析,既然要找到那个最大值,则一定要遍历每一种情况,即计算断开每一条边的情况。那么难点就变成了如何能快速得到断开形成的两棵子树的结点值之和。通过分析例子1可以看出,断开后的左边部分形成了根结点为2的一棵新的二叉树,需要知道其所有结点之和。

此时不难想到,若可以知道以任意结点为根结点的子树的结点之和,会大大利于计算。而后序遍历正好符合这种从底向上遍历的顺序,从叶结点开始,不停的往根结点遍历,同时可以累加遍历到的结点值,这样到达根结点时,就可以得到所有的结点值之和了。博主最开始想到的方法是建立每个结点跟以其为根结点的子树的结点和之间的映射,由于只看了例子1,认为计算乘积的方法就是结点1的映射值减去结点2的映射值,再乘以结点2的映射值就行了。但其实这种方法是不对的,只有在拆分与根结点相连的边的时候才行,比如例子2,拆分位置结点2的映射值是不包括结点1的,所以计算的结果肯定不对。

正确的方法是用整个树所有的结点值之和,减去断开点为根结点的子树之和,所以先要求出所有的结点之和,这里可以快速用一个先序遍历来得到,然后再用一个后序遍历来计算乘积,该递归函数的返回值是以输入的结点为根结点的子树的结点之和,乘积保存在引用参数 res 里。在后序遍历中,首先判空,若当前结点为空,则返回0,否则计算以当前结点为根结点的子树的结点之和,方法是当前结点值加上对左子结点调用递归的返回值,再加上对右子结点调用参数的返回值。此时更新乘积结果 res,用上面算出的结果 cur,乘以整个树结点之和 sum 减去 cur 的值即可,参见代码如下:


解法一:

class Solution {
public:
    int maxProduct(TreeNode* root) {
        long res = 0, sum = 0, M = 1e9 + 7;
        dfs(root, sum);
        helper(root, sum, res);
        return res % M;
    }
    void dfs(TreeNode* node, long& sum) {
        if (!node) return;
        sum += node->val;
        dfs(node->left, sum);
        dfs(node->right, sum);
    }
    int helper(TreeNode* node, long sum, long& res) {
        if (!node) return 0;
        int cur = node->val + helper(node->left, sum, res) + helper(node->right, sum, res);
        res = max(res, cur * (sum - cur));
        return cur;
    }
};

再来看一种更简洁的写法,这里并不需要一个单独的递归函数来计算整棵树的结点之和,而是可以利用上面的后序遍历的递归函数,因为其返回的就是以输入结点为根结点的子树的结点之和,而若输入的就是原来的根结点,则得到的就是整棵树的结点值和。但是由于此时输入的 sum 是0,所以得到的 res 结果也没有意义,需要再次调用递归函数,此时的 sum 就可以传入正确的值了,从而得到的 res 也是正确的,参见代码如下:


解法二:

class Solution {
public:
    int maxProduct(TreeNode* root) {
        long res = 0, sum = 0, M = 1e9 + 7;
        sum = dfs(root, sum, res);
        dfs(root, sum, res);
        return res % M;
    }
    int dfs(TreeNode* node, long sum, long& res) {
        if (!node) return 0;
        int cur = node->val + dfs(node->left, sum, res) + dfs(node->right, sum, res);
        res = max(res, cur * (sum - cur));
        return cur;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1339


类似题目:

Count Nodes With the Highest Score


参考资料:

https://leetcode.com/problems/maximum-product-of-splitted-binary-tree/

https://leetcode.com/problems/maximum-product-of-splitted-binary-tree/solutions/496496/java-two-pass-postorder-traversal/

https://leetcode.com/problems/maximum-product-of-splitted-binary-tree/solutions/496549/java-c-python-easy-and-concise/


LeetCode All in One 题目讲解汇总(持续更新中...)

标签:node,Binary,Product,cur,res,sum,结点,dfs,二叉树
From: https://www.cnblogs.com/grandyang/p/17289291.html

相关文章

  • 二叉树
         #include<bits/stdc++.h>usingnamespacestd;typedefstructTreeNode{ chardata; structTreeNode*LChild; structTreeNode*RChild;}Tree,LPTree;LPTree*creatNode(chardata);voidinsertNode(LPTree*parentNode,LPTree*LChild,LPTree......
  • 汉诺塔与二进制、满二叉树的千丝万缕
    汉诺塔(TowerofHanoi)源于印度传说中,大梵天创造世界时造了三根金钢石柱子,其中一根柱子自底向上叠着64片黄金圆盘。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。汉诺塔递归算法3......
  • 222. 完全二叉树的节点个数
    给你一棵完全二叉树的根节点root,求出该树的节点个数。完全二叉树的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第h层,则该层包含1~2h个节点。classSolution{public:......
  • 111. 二叉树的最小深度
    给定一个二叉树,找出其最小深度。最小深度是从根节点到最近叶子节点的最短路径上的节点数量。说明:叶子节点是指没有子节点的节点。classSolution{public:intminDepth(TreeNode*root){if(root==nullptr)return0;if(!root->left&&!root->right......
  • 104.二叉树的最大深度
    给定一个二叉树,找出其最大深度。二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。说明:叶子节点是指没有子节点的节点。示例:给定二叉树[3,9,20,null,null,15,7],classSolution{public:intgetdepth(TreeNode*node){if(node==NULL)return0;......
  • 代码随想录Day20-Leetcode654.最大二叉树,617.合并二叉树,700.二叉搜索树中的搜索,98.验
    654.最大二叉树题目链接:https://leetcode.cn/problems/maximum-binary-tree/基本的模拟思路很快/***Definitionforabinarytreenode.*functionTreeNode(val,left,right){*this.val=(val===undefined?0:val)*this.left=(left===undefined......
  • 树:剑指 Offer 37. 序列化二叉树
    题目描述:请实现两个函数,分别用来序列化和反序列化二叉树。你需要设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列/反序列化算法执行逻辑,你只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。提示:输入输出格式与LeetCo......
  • 最小覆盖子串(哈希表、字符串)、两数之和(数组、哈希表)、二叉树的层序遍历 II(树、广
    最小覆盖子串(哈希表、字符串)给你一个字符串s、一个字符串t。返回s中涵盖t所有字符的最小子串。如果s中不存在涵盖t所有字符的子串,则返回空字符串""。**注意:**如果s中存在这样的子串,我们保证它是唯一的答案。示例1:输入:s="ADOBECODEBANC",t="ABC"输出:"B......
  • magento 在产品页添加评论 Add Review Form in Magento Product View Page
    Magento产看产品评论需要点击到另外一个页面中,这种设计对于用户体验和SEO都相当不利。一方面用户无法在产品页面查看该产品的一些用户评价,另外,搜索引擎也会收录很多与产品无关的页面。那么如何让产品评论直接显示在产品页面呢?我们需要修改一下模板文件,很简单即可实现。 首先,在lay......
  • 【数据结构】二叉树先序、中序、后序及层次遍历(C语言版)
    一、图示展示1.先序遍历先序遍历可以想象为,一个小人从一棵二叉树根节点为起点,沿着二叉树外沿,逆时针走一圈回到根节点,路上遇到的元素顺序,就是先序遍历的结果先序遍历结果为:ABDHIEJCFKG动画演示:记住小人沿着外围跑一圈(直到跑回根节点),多看几次动图便能理解2.......