题目描述
给你一棵二叉树,它的根为 root
。请你删除 1 条边,使二叉树分裂成两棵子树,且它们子树和的乘积尽可能大。
由于答案可能会很大,请你将结果对 10^9 + 7
取模后再返回。
样例
输入:root = [1,2,3,4,5,6]
输出:110
解释:删除红色的边,得到 2 棵子树,和分别为 11 和 10 。它们的乘积是 110 (11*10)
输入:root = [1,null,2,3,4,null,null,5,6]
输出:90
解释:移除红色的边,得到 2 棵子树,和分别是 15 和 6 。它们的乘积为 90 (15*6)
输入:root = [2,3,9,10,7,8,6,5,4,11,1]
输出:1025
输入:root = [1,1]
输出:1
限制
- 每棵树最多有
50000
个结点,且至少有2
个结点。 - 每个结点的值在
[1, 10000]
之间。
算法
(递归遍历) $O(n)$
- 第一次递归遍历记录下每个点及其子树的和,同时可以得到整个树的总和。
- 第二次递归遍历,枚举每一条边,然后计算答案。
时间复杂度
- 每个点仅被遍历两次,故时间复杂度为 $O(n)$。
空间复杂度
- 需要额外 $O(n)$ 的空间记录每个点及其子树的和。
C++ 代码
/**
* 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:
#define LL long long
LL ans;
unordered_map<TreeNode*, int> sum;
void get_sum(TreeNode *rt) {
if (rt == NULL)
return;
get_sum(rt -> left);
get_sum(rt -> right);
sum[rt] = sum[rt -> left] + sum[rt -> right] + rt -> val;
}
void solve(TreeNode *rt, int S) {
if (rt == NULL)
return;
ans = max(ans, (LL)(S - sum[rt -> left]) * sum[rt -> left]);
ans = max(ans, (LL)(S - sum[rt -> right]) * sum[rt -> right]);
solve(rt -> left, S);
solve(rt -> right, S);
}
int maxProduct(TreeNode* root) {
const int MOD = 1000000007;
ans = 0;
sum[NULL] = 0;
get_sum(root);
solve(root, sum[root]);
return ans % MOD;
}
};