题目三:
解法一:(递归)
解题思路:这个题我想自己写,大致思路对了,就是对于左叶子没定义好,导致没写出来。这个题的递归思路就是:使用闭包定义sum,递归逻辑中,遇到当前节点的左节点是左叶子节点时,就加上当前节点的左叶子结点数值,使用前中后序递归遍历都可。
左叶子的明确定义:节点A的左孩子不为空,且左孩子的左右孩子都为空(说明是叶子节点),那么A节点的左孩子为左叶子节点。 不能判断本结点是不是左叶子结点,需要通过节点的父节点来判断其左孩子是不是左叶子。
平时我们解二叉树的题目时,已经习惯了通过节点的左右孩子判断本节点的属性,而本题我们要通过节点的父节点判断本节点的属性。
var sumOfLeftLeaves = function(root) {
let sum = 0
var leftNodesSum = function(cur) {
// 遇到空结点
if (cur === null) return 0
// 遇到左孩子结点
if (cur.left !== null && cur.left.left === null && cur.left.right === null) {
sum += cur.left.val
}
leftNodesSum(cur.left)
leftNodesSum(cur.right)
}
leftNodesSum(root)
return sum
};
解法二:(迭代法)
解题思路:一直迭代遍历每一个结点,如果是左叶子结点就算入总和,可以使用前中后以及层序遍历。
var sumOfLeftLeaves = function(root) {
if (root === null) return 0
let stack = [root]
let sum = 0
while(stack.length) {
let node = stack.pop()
if (node.left !== null && node.left.left === null && node.left.right === null) {
sum += node.left.val
}
node.right && stack.push(node.right)
node.left && stack.push(node.left)
}
return sum
};
解法三:(参考他人)
写一个辅助函数,求当前子树的所有左叶子之和,有一个参数 isLeft:当前子树是否为左子树。
当遍历的是 null 节点,返回 0。
当遍历的是叶子节点,根据 isLeft 判断,是左叶子节点就返回 root.val,不是就返回 0。
当遍历到别的节点,递归它们的左、右子树,isLeft 分别传 true 和 false,返回值相加并返回,
const sumOfLeftLeaves = (root) => {
const dfs = (root, isLeft) => {
if (root == null) return 0;
if (root.left == null && root.right == null) {
if (isLeft) return root.val;
return 0;
}
return dfs(root.left, true) + dfs(root.right, false);
};
return dfs(root, false);
};
也可以把 isLeft 拿出来作为一个标识变量:
const sumOfLeftLeaves = (root) => {
if (root == null) return 0;
let sum = 0;
let isLeft = false;
const dfs = (root) => {
if (root.left == null && root.right == null) {
if (isLeft) sum += root.val;
return;
}
if (root.left) {
isLeft = true;
dfs(root.left);
}
if (root.right) {
isLeft = false;
dfs(root.right);
}
};
dfs(root);
return sum;
};