给你一棵二叉树,它的根为 root
。请你删除 1 条边,使二叉树分裂成两棵子树,且它们子树和的乘积尽可能大。
由于答案可能会很大,请你将结果对 10^9 + 7 取模后再返回。
示例 1:
输入:root = [1,2,3,4,5,6] 输出:110 解释:删除红色的边,得到 2 棵子树,和分别为 11 和 10 。它们的乘积是 110 (11*10)
示例 2:
输入:root = [1,null,2,3,4,null,null,5,6] 输出:90 解释:移除红色的边,得到 2 棵子树,和分别是 15 和 6 。它们的乘积为 90 (15*6)
示例 3:
输入:root = [2,3,9,10,7,8,6,5,4,11,1] 输出:1025
示例 4:
输入:root = [1,1] 输出:1
提示:
- 每棵树最多有
50000
个节点,且至少有2
个节点。 - 每个节点的值在
[1, 10000]
之间。
Related Topics
题解
1.求出二叉树总和
2.找到一个节点上的总和,最接近于树上总和的一半
3.求出面积即是结果
4.为啥是一半呢,看代码中间的注释
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
double sum = 0;
double halfSum = 0;
double nearHalf = 0;
public int maxProduct(TreeNode root) {
//两数之和固定,两数需要乘积最大化,则两个数应当无限接近,最优解为两数之和的一半
//类似于一根固定长的绳子摆成矩形的两个相邻边,要求使矩形面积最大化,这是一个高中还是初中数学题来着
//假设这条绳子长为 2x,分成两段
// 一段长度为 x - t , 另一段的长度就为 x + t
//( x - t )* ( x + t ) <= x^2
// x^2 + x*t - x*t - t^2 <= x^2
// x^2 - t^2 <= x^2
// 有且只有当t = 0 的时候面积最大
sum = dfs(root);
halfSum = sum/2;
dfsNearHalf(root);
return (int)((sum-nearHalf)*nearHalf%1000000007);
}
private double dfsNearHalf(TreeNode node){
if(node==null){
return 0;
}
double tempSum = node.val + dfsNearHalf(node.left) + dfsNearHalf(node.right);
nearHalf = Math.abs(nearHalf - halfSum) > Math.abs(tempSum-halfSum)?tempSum:nearHalf;
return tempSum;
}
private double dfs(TreeNode node){
if(node==null){
return 0;
}
return node.val + dfs(node.left) + dfs(node.right);
}
}
//leetcode submit region end(Prohibit modification and deletion)
其实也可以第一DFS之后把结果缓存起来,在然后遍历缓存起来的结果,找到最接近的那个,或者在第二次dfs的之后从缓存里取结果,而不是再算一次,但是这两种我都试了下。效率还没有再算一次的效率高。
发表评论