题目1:404.左叶子之和
这一题的难点就在于:不能直接判断当前的节点是不是左叶子,比如示例中的7,需要根据他的根节点20来判断7是不是左叶子
因此需要通过节点的父节点来判断其左孩子是不是左叶子
如果某一节点的左节点不为空、左节点的左右节点为空,则该节点的左节点为左叶子。
解法一:递归法
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if (root == NULL) return 0;
int leftValue = sumOfLeftLeaves(root->left); // 左
int rightValue = sumOfLeftLeaves(root->right); // 右
int midValue = 0; // 中
if (root->left && !root->left->left && !root->left->right) { //当某个节点的左节点不为空但左节点的左右节点为空,那么这个节点的左节点为左叶子
midValue = root->left->val;
}
int sum = midValue + leftValue + rightValue;
return sum;
}
};
简化后:
class Solution {
public:
int sumOfLeftLeaves(TreeNode* root) {
if (root == NULL) return 0;
return (root->left != NULL && root->left->left == NULL && root->left->right == NULL ? root->left->val : 0) + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);
}
};
解法二:迭代法
写法和之前的迭代法差不多,思路和递归法差不多
class Solution {
public:
int sum0fLeftLeaves(TreeNode* root) {
stack<TreeNode*>st;
if (root == NULL) return 0;
st.push(root);
int result = 0;
while (!st.empty()) {
TreeNode* node = st.top();
st.pop();
if (node->left != NULL && node->left->left != NULL && node->left->right == NULL) {
result += node->left->val;
}
if (node->right) st.push(node->right);
if (node->left) st.push(node->left);
}
return result;
}
};
题目2:513.找树左下角的值
解法一:迭代法
找最底层的最左边节点的值,可以用层序遍历
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*>que;
if (root != NULL) que.push(root);
int result = 0;
while (!que.empty()) {
int size = que.size();
for (int i = 0; i < size; i++) {
TreeNode* node = que.front();
que.pop();
if (i == 0) result = node->val; //记录每一行第一个元素直到最后一行
if (node->left) que.push(node->left);
if (node->right) que.push(node->right);
}
}
return result;
}
};
解法二:递归法
最后一行的最左边的值
那么可以定义一个深度最大值,每次更新最大深度;
最左边的值,可以先遍历左子树,再遍历右子树
class Solution {
public:
int maxdepth = INT_MIN; //全局变量,记录最大深度
int maxdepthvalue; //全局变量,记录最大深度最左节点的数值
void traversal(TreeNode* root, int depth) { //传入根节点、depth记录当前深度
if (root->left == NULL && root->right == NULL) { //遇到叶子节点
if (depth > maxdepth) { //如果当前遍历的深度大于最大深度
maxdepth = depth; //更新最大深度
maxdepthvalue = root->val; //更新最大深度最左节点的数值
}
return;
}
if (root->left) { //左
depth++; //深度加一
traversal(root->left, depth);
depth--; //回溯,深度减一
}
if (root->right) {
depth++;
traversal(root->right, depth);
depth--;
}
return;
}
int findBottemLeftValue(TreeNode* root) {
traversal(root,0);
return maxdepthvalue;
}
};
根据评论区大佬进行了简单的化简:
class Solution {
public:
int maxdepth = -1;
int maxleftvalue;
void traversal(TreeNode* root, int depth) {
if (root== NULL) return;
if (depth > maxdepth) {
maxleftvalue = root->val;
maxdepth++;
}
traversal(root->left, depth + 1);
traversal(root->right, depth + 1);
}
int findBottomLeftValue(TreeNode* root) {
traversal(root, 0);
return maxleftvalue;
}
};
题目3:112.路径之和
如果需要遍历整棵树,递归函数就不能有返回值。如果需要遍历某一条固定路线,递归函数就一定要有返回值。
这里关于递归函数返回值,有一个说法:
如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。
如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。
如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。
解法一:递归法
class Solution {
public:
bool traversal(TreeNode* node, int count) { //传入根节点,count计算二叉树一边之和、通过递减让count减去路径上节点的值
if (node->left == NULL && node->right == NULL && count == 0) return true; //遇到叶子节点且计数为0,则找到了符合目标和的边
if (node->left == NULL && node->right == NULL) return false; //遇到叶子节点但count不为0,则没有找到符合条件的边
if (node->left) { //左(空节点不遍历)
//count -= node->left->val;
//if (traversal(node->left, count)) return true; //递归
//count += node->left->val; //回溯,撤销处理结果
if (traversal(node->left, count - node->left->val)) return true; //把count - cur->left->val 直接作为参数传进去,函数结束,count的数值没有改变。
}
if (node->right) {
//count -= node->right->val;
//if (traversal(node->right, count)) return true;
//count += node->left->val;
if (traversal(node->right, count - node->right->val)) return true;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == NULL) return false;
return traversal(root, targetSum - root->val); //先减去头结点的值
}
};
代码精简后:
class solution {
public:
bool haspathsum(treenode* root, int sum) {
if (root == null) return false;
if (!root->left && !root->right && sum == root->val) {
return true;
}
return haspathsum(root->left, sum - root->val) || haspathsum(root->right, sum - root->val);
}
};
题目4:113.路径之和Ⅱ
解题思路和112差不多
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void traversal(TreeNode* node, int count) { //遍历整棵树,递归函数不需要返回值
if (node->left == NULL && node->right == NULL && count == 0) {
result.push_back(path);
return;
}
if (node->left && node->right) return;
if (node->left) { //这里隐藏了判空
path.push_back(node->left->val);
count -= node->left->val;
traversal(node->left, count); // 递归
count += node->left->val; // 回溯
path.pop_back(); // 回溯
}
if (node->right) {
path.push_back(node->right->val);
count -= node->right->val;
traversal(node->right, count);
count += node->right->val;
path.pop_back();
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if (root == nullptr) return result;
path.push_back(root->val);
traversal(root, targetSum - root->val);
return result;
}
};
精简后的代码:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void traversal(TreeNode* node, int count) {
if (node == nullptr) return;
path.push_back(node->val);
count -= node->val;
if (node->left == nullptr && node->right == nullptr && count == 0) {
result.push_back(path);
}
traversal(node->left, count);
traversal(node->right, count);
path.pop_back();
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
traversal(root, targetSum);
return result;
}
};