[力扣每日习题][1339]. 分裂二叉树的最大乘积 2026.01.07

**难度评级:**中等

题目:

给你一棵二叉树,它的根为 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)

解题思路:DFS

可以先计算得到所有节点的和 ,再通过数组存储所有子树的和 ,遍历数组的时候,计算:子树和 × (所有节点和 - 子树和),也就是分割成两个子树的乘积,找出最大的那一个乘积即可。

深度优先搜索就是沿着一条路走到底,走不通了再回到上一层继续走。可以采用递归的方式实现,将根节点作为起始节点放入函数当中,函数需要完成如下操作:

① 定义 left 、 right、temp 3个参数,每次调用 DFS 函数的时候都需要重置为 0 ;

② 判断是否有左孩子,有就调用 DFS 函数,并且将函数的返回值存入 left 中,没有就下一步;

③ 判断是否有右孩子,有就调用 DFS 函数,并且将函数的返回值存入 right 中,没有就下一步;

④ 计算 temp = left + right + 当前节点的值;

⑤ 将 temp 存入子树和的数组中。

⑥ 返回 temp(当前子树的和);


解析:根节点调用 DFS 函数的时候,会一直嵌套直到找到二叉树**最左边的那个叶子节点,**接下来,由于 left 和 right 为 0,那么 temp = 0 + 0 + 当前节点的值,将 temp 返回至上一层,也就是当前节点的父亲节点,父亲节点已经完成了 ② ,在这一层 left 的值是刚才计算得到的 temp,接下来进行 ③ ,如果没有右孩子那么 right = 0,在这一层的 temp = left + 0 + 当前节点的值,结束这层循环,再返回上一层。

理解 DFS 的关键就是,先找到一条路一直到底,然后再慢慢往回退

接下来我们用一颗二叉树来模拟一下这个 DFS 的流程。


以如下二叉树为例,依次分析每个节点,下面是根节点的初始状态,将各个参数重置为 0,temp是当前节点孩子子树的和+当前节点值;注意这里的left 和 right 分别指的左孩子子树的和、右孩子子树的和,不是左孩子和右孩子的值,在代码中为 left = DFS(2);right = DFS(3);是递归调用函数后返回的值。


对于 1 这个节点,它有左孩子,那么这里需要递归调用 DFS 函数,将 2 这个节点作为根节点进行分析,对应着步骤 ②,2 这个节点进入后,它需要开始循环它的 DFS 函数。


节点 2 有左孩子 4,那么将节点 4 作为根节点进行分析,调用 DFS 函数。


此时节点 4 ,进行步骤 ②、③,由于它没有孩子,那么只能进行步骤 ④,计算 temp,最后将计算结果保存。


第三层 4 进行步骤 ⑥,返回上一层,将计算结果返回给上一层对应调用 DFS(4)的那个参数,上一层调用 DFS(4)的是第二层 2 在步骤 ② 的时候将左孩子进行递归调用 DFS,那么值就返回给第二层 2 的参数 left


第二层 2 的步骤 ② 结束,现在进行步骤 ③ ,它有右孩子,那么将节点 5 调用 DFS 函数,作为根节点进行分析。


节点 5,没有左右孩子,直接进行步骤 ④。


进行步骤 ⑥,将值返回给上一层的 right。


现在第三层 5 结束,第二层 2 进行步骤 ④,计算它自己的 temp。


第二层 2 ,进行步骤 ⑥,将值返回给上一层的 left。


第二层 2 结束,现在对一层 1 进行步骤 ③,它有右孩子,将右孩子递归调用 DFS


节点 3 ,它没有左孩子,只有右孩子,那么它直接进行步骤 ③。


第三层 6 ,没有孩子,是叶子节点,直接步骤 ④,计算 temp。


进行步骤 ⑥,返回上一层,将值给上一层的 right。


第二层 3 进行步骤 ④。


进行步骤 ⑥,返回上一层,将值返回给上一层的 right。


第一层 1 进行步骤 ④。


最后进行步骤 ⑥,将最后的值返回即可,在递归调用的时候,所有的子树和都已计算并保存至一个数组,接下来只需要遍历数组,计算 每棵子树和 * (总和 - 该子树和) 找到最大值就可以了。


题解代码如下:

复制代码
/**
 * 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:
    const int MOD = 1e9 + 7;
    long long dfs(TreeNode* root, vector<long long>& list){
        long long l = 0;
        long long r = 0;
        long long temp = 0;
        if (root -> left != nullptr){
            l = dfs(root -> left, list);
        }
        if (root -> right != nullptr){
            r = dfs(root -> right, list);
        }
        temp = l + r + root -> val;
        list.push_back(temp);
        return temp;
    }

    int maxProduct(TreeNode* root) {
        vector <long long> list;    // 用于存储所有子树和
        long long sum = dfs(root, list);
        long long res = 0;
        for (auto i:list){
            long long cal = i * (sum - i);
            if (cal > res){
                res = cal;
            }
        }
        return res % MOD;
    }
};

**优化思路:**暂无。

相关推荐
hrrrrb3 小时前
【算法设计与分析】贪心算法
算法·贪心算法·代理模式
TracyCoder1233 小时前
LeetCode Hot100(10/100)—— 53. 最大子数组和
算法·leetcode
Σίσυφος19004 小时前
霍夫变换vs LS vs RANSAC 拟合直线 MATLAB实现
算法·计算机视觉·matlab
假女吖☌4 小时前
限流算法-redis实现与java实现
java·redis·算法
蒟蒻的贤4 小时前
两数之和。
算法
wen__xvn5 小时前
代码随想录算法训练营DAY27第八章 贪心算法 part01
算法·贪心算法
We་ct5 小时前
LeetCode 125. 验证回文串:双指针解法全解析与优化
前端·算法·leetcode·typescript
客卿1235 小时前
力扣20-有效括号(多家面试题)
算法·leetcode·职场和发展
木井巳5 小时前
【递归算法】快速幂解决 pow(x,n)
java·算法·leetcode·深度优先