目录
404.左叶子之和
计算给定二叉树的所有左叶子之和。
示例:
给定二叉树的根节点 root
,返回所有左叶子之和。
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if (root == NULL) return 0;
if (root->left == NULL && root->right== NULL) return 0;
int leftValue = sumOfLeftLeaves(root->left); // 左
if (root->left && !root->left->left && !root->left->right) { // 左子树就是一个左叶子的情况
leftValue = root->left->val;
}
int rightValue = sumOfLeftLeaves(root->right); // 右
int sum = leftValue + rightValue; // 中
return sum;
}
};
如果改成所有左节点之和呢:
cpp
class Solution {
public:
int sumOfLeftSubtrees(TreeNode* root) {
if (root == NULL) return 0;
int leftSum = 0;
if (root->left != NULL) { // 如果有左子树,则加入左子树根节点的值
leftSum += root->left->val + sumOfLeftSubtrees(root->left); // 加上左子树的和
}
int rightSum = sumOfLeftSubtrees(root->right); // 遍历右子树
return leftSum + rightSum;
}
};
513.找树左下角的值
给定一个二叉树,在树的最后一行找到最左边的值。
示例 1:
这个需要回溯。
回溯逻辑分析
-
深度参数传递
- 在进入
traversal(root->left, depth)
和traversal(root->right, depth)
时,先增加depth++
,表示进入更深的一层。 - 在递归调用完成后,通过
depth--
将深度恢复到调用前的状态。 - 回溯的本质:通过递归函数返回时,深度回到之前的值,这样确保每个分支的递归是独立的,互不干扰。
- 在进入
-
叶子节点处理
- 当到达叶子节点时,判断当前深度是否大于已记录的最大深度(
maxDepth
),如果是,则更新result
和maxDepth
。 - 叶子节点处理完成后递归返回,此时调用栈回到父节点,深度恢复到进入当前节点前的状态。
- 当到达叶子节点时,判断当前深度是否大于已记录的最大深度(
cpp
/**
* 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:
int maxDepth=-1;
int result=1;
int findBottomLeftValue(TreeNode* root) {
traversal(root,0);
return result;
}
void traversal(TreeNode* root,int depth){
if (root == nullptr) return; // 空节点直接返回
if(root->left==nullptr&&root->right==nullptr){
if(depth>maxDepth){
maxDepth=depth;
result = root->val;
}
}
if(root->left){
depth++;
traversal(root->left,depth);
depth--;
}
if(root->right){
depth++;
traversal(root->right,depth);
depth--;
}
}
};
也可以不用这么每次要depth++,depth--太麻烦了,直接传递 depth+1
原因:直接使用 depth + 1
是因为在递归函数中,参数是值传递的。换句话说,传递给函数的 depth
是一个拷贝,而不是对原始变量的引用。因此,在递归过程中修改 depth
对当前函数外的调用不会有任何影响,这就避免了手动恢复 depth
的复杂性。
优化后的代码:
cpp
void traversal(TreeNode* root, int depth) {
if (root == nullptr) return;
if (root->left == nullptr && root->right == nullptr) {
if (depth > maxDepth) {
maxDepth = depth;
result = root->val;
}
}
traversal(root->left, depth + 1); // 左子树
traversal(root->right, depth + 1); // 右子树
}
112.路径总和
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
同样的下面一道题也是利用递归的思路:
cpp
/**
* 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:
bool hasPathSum(TreeNode* root, int targetSum) {
return checkPathSum(root, 0, targetSum); // 从根节点开始递归
}
private:
bool checkPathSum(TreeNode* root, int currentSum, int targetSum) {
if (root == nullptr) return false; // 遇到空节点返回 false
// 累加当前节点的值
currentSum += root->val;
// 如果是叶子节点,检查路径和是否等于目标值
if (root->left == nullptr && root->right == nullptr) {
return currentSum == targetSum;
}
// 递归检查左右子树
return checkPathSum(root->left, currentSum, targetSum) ||
checkPathSum(root->right, currentSum, targetSum);
}
};