① 定义 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);是递归调用函数后返回的值。
/**
* 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;
}
};