我在代码随想录|写代码Day18之二叉树-404. 左叶子之和,513. 找树左下角的值,112. 路径总和,113. 路径总和 II
学习目标:
博主介绍: 27dCnc
专题 : 数据结构帮助小白快速入门
👍👍👍👍👍👍👍👍👍👍👍👍
☆*: .。. o(≧▽≦)o .。.:*☆
主题: 二叉树
今日份打卡
- 代码随想录-二叉树
文章目录
- 学习目标:
- 主题: 二叉树
- 学习内容:
- [404. 左叶子之和](https://leetcode.cn/problems/sum-of-left-leaves/description/)
- [513. 找树左下角的值](https://leetcode.cn/problems/find-bottom-left-tree-value/description/)
- [112. 路径总和](https://leetcode.cn/problems/path-sum/description/)
- [113. 路径总和 II](https://leetcode.cn/problems/path-sum-ii/description/)
- 学习时间:
- 学习产出:
学习内容:
- 左叶子之和
- 找树左下角的值
- 路径总和
- 路径总和 II
404. 左叶子之和
题目
思路
本题要找出树的最后一行的最左边的值。此时大家应该想起用层序遍历是非常简单的了,反而用递归的话会比较难一点。
代码
1
class Solution {
public:
int sumOfLeftLeaves(TreeNode* node) {
if(node == nullptr) return 0;
if(node->left == nullptr&&node->right== nullptr) return 0;
int leftsum = sumOfLeftLeaves(node->left);
if(node->left && !node->left->left && !node->left->right) {
leftsum = node->left->val;
}
int rightsum = sumOfLeftLeaves(node->right);
return leftsum + rightsum;
}
};
2
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;
}
};
513. 找树左下角的值
题目
思路
将树遍历到树的最底层六花取最底层的左孩子,
代码
class Solution {
public:
int maxDepth = INT_MIN;
int result;
void traversal(TreeNode*root,int depth) {
if(root ->left == NULL && root->right == NULL) {
if(depth > maxDepth ) {
maxDepth = depth;
result = root->val;
}
return ;
}
if(root->left) {
depth++;
traversal(root->left,depth);
depth--;
}
if(root->right) {
depth++;
traversal(root->right,depth);
depth--;
}
return ;
}
int findBottomLeftValue(TreeNode* root) {
traversal(root,0);
return result;
}
};
精简版代码
class Solution {
public:
int maxDepth = INT_MIN;
int result;
void traversal(TreeNode* root, int depth) {
if (root->left == NULL && root->right == NULL) {
if (depth > maxDepth) {
maxDepth = depth;
result = root->val;
}
return;
}
if (root->left) {
traversal(root->left, depth + 1); // 隐藏着回溯
}
if (root->right) {
traversal(root->right, depth + 1); // 隐藏着回溯
}
return;
}
int findBottomLeftValue(TreeNode* root) {
traversal(root, 0);
return result;
}
};
112. 路径总和
题目
可以使用深度优先遍历的方式(本题前中后序都可以,无所谓,因为中节点也没有处理逻辑)来遍历二叉树
- 确定递归函数的参数和返回类型
参数:需要二叉树的根节点,还需要一个计数器,这个计数器用来计算二叉树的一条边之和是否正好是目标和,计数器为int型。
再来看返回值,递归函数什么时候需要返回值?
什么时候不需要返回值?这里总结如下三点:
如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。
如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。
如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。
而本题我们要找一条符合条件的路径,所以递归函数需要返回值,及时返回,那么返回类型是什么呢?
如图所示:
图中可以看出,遍历的路线,并不要遍历整棵树,所以递归函数需要返回值,可以用bool类型表示。
所以代码如下:
bool traversal(treenode* cur, int count) // 注意函数的返回类型
- 确定终止条件
首先计数器如何统计这一条路径的和呢?
不要去累加然后判断是否等于目标和,那么代码比较麻烦,可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。
如果最后count == 0,同时到了叶子节点的话,说明找到了目标和。
如果遍历到了叶子节点,count不为0,就是没找到。
递归终止条件代码如下:
if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
if (!cur->left && !cur->right) return false; // 遇到叶子节点而没有找到合适的边,直接返回
- 确定单层递归的逻辑
因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。
递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。
代码如下:
if (cur->left) { // 左 (空节点不遍历)
// 遇到叶子节点返回true,则直接返回true
if (traversal(cur->left, count - cur->left->val)) return true; // 注意这里有回溯的逻辑
}
if (cur->right) { // 右 (空节点不遍历)
// 遇到叶子节点返回true,则直接返回true
if (traversal(cur->right, count - cur->right->val)) return true; // 注意这里有回溯的逻辑
}
return false;
以上代码中是包含着回溯的,没有回溯,如何后撤重新找另一条路径呢。
回溯隐藏在traversal(cur->left, count - cur->left->val)这里, 因为把count - cur->left->val 直接作为参数传进去,函数结束,count的数值没有改变。
为了把回溯的过程体现出来,可以改为如下代码:
if (cur->left) { // 左
count -= cur->left->val; // 递归,处理节点;
if (traversal(cur->left, count)) return true;
count += cur->left->val; // 回溯,撤销处理结果
}
if (cur->right) { // 右
count -= cur->right->val;
if (traversal(cur->right, count)) return true;
count += cur->right->val;
}
return false;
整体代码如下:
class Solution {
public:
bool hasPathSum(TreeNode* root, int sum) {
if(!root) 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);
}
};
其他解法
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (!root)
return false;
stack<TreeNode*> sNode;
stack<int> sSum;
//s.push(root);
int sum = 0;
TreeNode* cur = root;
while(!sNode.empty() || cur)
{
if (!cur)
{
cur = sNode.top();
sNode.pop();
sum = sSum.top();
sSum.pop();
}
while (cur)
{
sum += cur->val;
if (cur->left)
{
if (cur->right)
{
sNode.push(cur->right);
sSum.push(sum);
}
cur = cur->left;
}
else if (cur->right)
{
cur = cur->right;
}
else{
cur = nullptr;
}
}
if (sum == targetSum)
{
return true;
}
}
return false;
}
};
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum){
if(root == nullptr)
return false;
if(root->left == nullptr && root->right == nullptr)
return targetSum == root->val;
return hasPathSum(root->left, targetSum - root->val) ||
hasPathSum(root->right, targetSum - root->val);
}
};
113. 路径总和 II
题目
代码
class Solution {
public:
vector<vector<int>>vec;
vector<int>v;
void traval(TreeNode*cur,int count) {
if (!cur->left && !cur->right && count == 0) {
vec.push_back(v);
return ;
}
if (!cur->left && !cur->right) return ;
if (cur->left) {
v.push_back(cur->left->val);
count -= (cur->left->val);
traval(cur->left,count);
count += (cur->left->val);
v.pop_back();
}
if (cur->right) {
v.push_back(cur->right->val);
count -= (cur->right->val);
traval(cur->right,count);
count += (cur->right->val);
v.pop_back();
}
return ;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vec.clear();v.clear();
if (root == nullptr) return vec;
v.push_back(root->val);
traval(root,targetSum - root-> val);
return vec;
}
};
学习时间:
- 周一至周五晚上 7 点—晚上9点
- 周六上午 9 点-上午 11 点
- 周日下午 3 点-下午 6 点
学习产出:
- 技术笔记 2 遍
- CSDN 技术博客 3 篇
- 习的 vlog 视频 1 个
本文作者:2c237c6
本文链接:https://www.cnblogs.com/27dCnc/p/18568652
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步