_16LeetCode代码随想录算法训练营第十六天-C++二叉树 | 513.找树左下角的值、112.路径总和、113.路径总和ii、106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树
题目列表
- 513.找树左下角的值
- 112.路径总和
- 113.路径总和ii
- 106.从中序与后序遍历序列构造二叉树
- 105.从前序与中序遍历序列构造二叉树
513.找树左下角的值
代码随想录地址:https://programmercarl.com/0513.%E6%89%BE%E6%A0%91%E5%B7%A6%E4%B8%8B%E8%A7%92%E7%9A%84%E5%80%BC.html
题目
给定一个二叉树的 根节点 root
,请找出该二叉树的 最底层 最左边 节点的值。
假设二叉树中至少有一个节点。
示例 1:
输入: root = [2,1,3]
输出: 1
示例 2:
输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7
提示:
- 二叉树的节点个数的范围是 [1, 1 0 4 10^4 104]
- - 2 31 2^{31} 231 <= Node.val <= $2^{31} $- 1`
代码
递归代码
有点复杂。
/*
* @lc app=leetcode.cn id=513 lang=cpp
*
* [513] 找树左下角的值
*/
// @lc code=start
/**
* 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 {
private:
int maxDepth = INT_MIN;
int result;
void traverse(TreeNode* node, int depth)
{
//终止条件
if(node->left == nullptr && node->right == nullptr)
{
if(depth > maxDepth)
{
maxDepth = depth;
result = node->val;
}
}
//递归
if(node->left != nullptr)
{
depth++;
traverse(node->left, depth);
depth--;//回溯
}
if(node->right != nullptr)
{
depth++;
traverse(node->right, depth);
depth--;//回溯
}
}
public:
int findBottomLeftValue(TreeNode* root) {
traverse(root, 1);
return result;
}
};
// @lc code=end
非递归代码
/*
* @lc app=leetcode.cn id=513 lang=cpp
*
* [513] 找树左下角的值
*/
// @lc code=start
/**
* 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 findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
int res = 0;
if(root != nullptr)
que.push(root);
while(!que.empty())
{
int size = que.size();
for(int i = 0; i < size; i++)
{
TreeNode* node = que.front();
que.pop();
//这个条件最开始没想到,需要注意一下
if(i == 0)
res = node->val;
if(node->left != nullptr)
que.push(node->left);
if(node->right != nullptr)
que.push(node->right);
}
}
return res;
}
};
// @lc code=end
112.路径总和
代码随想录地址:https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html
题目
给你二叉树的根节点 root
和一个表示目标和的整数 targetSum
。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。如果存在,返回 true
;否则,返回 false
。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。
示例 2:
输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。
示例 3:
输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。
提示:
- 树中节点的数目在范围
[0, 5000]
内 -1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
思路
递归什么时候需要返回值?
- 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(113.路径总和ii)
- 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (236. 二叉树的最近公共祖先 )
- 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)
代码
递归代码
/*
* @lc app=leetcode.cn id=112 lang=cpp
*
* [112] 路径总和
*/
// @lc code=start
/**
* 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 {
private:
bool traverse(TreeNode* node, int count)
{
//到叶子节点并且count计数为0,返回true
if(node->left == nullptr && node->right == nullptr && count == 0)
return true;
//到叶子节点但是count计数不为0,返回false
if(node->left == nullptr && node->right == nullptr)
return false;
//如果当前node的左孩子不为空,则向左孩子递归
//回溯隐藏在count - node->left->val
if(node->left != nullptr)
if(traverse(node->left, count - node->left->val)) return true;
//如果当前node的右孩子不为空,则向右孩子递归
//回溯隐藏在count - node->right->val
if(node->right != nullptr)
if(traverse(node->right, count - node->right->val)) return true;
//以上情况都不满足时,返回false
return false;
}
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr)
return false;
return traverse(root, targetSum - root->val);
}
};
// @lc code=end
非递归代码-迭代代码
需要使用pair对象
/*
* @lc app=leetcode.cn id=112 lang=cpp
*
* [112] 路径总和
*/
// @lc code=start
/**
* 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) {
queue<pair<TreeNode*, int> > que;
if(root == nullptr)
return false;
que.push(pair<TreeNode*, int>(root, root->val));
while(!que.empty())
{
pair<TreeNode*, int> node = que.front();
que.pop();
if(node.first->left == nullptr && node.first->right == nullptr && node.second == targetSum)
return true;
if(node.first->left)
que.push(pair<TreeNode*, int>(node.first->left, node.second + node.first->left->val));
if(node.first->right)
que.push(pair<TreeNode*, int>(node.first->right, node.second + node.first->right->val));
}
return false;
}
};
// @lc code=end
113.路径总和ii
代码随想录地址:https://programmercarl.com/0112.%E8%B7%AF%E5%BE%84%E6%80%BB%E5%92%8C.html
题目
给你二叉树的根节点 root
和一个整数目标和 targetSum
,找出所有 从根节点到叶子节点 路径总和等于给定目标和的路径。
叶子节点 是指没有子节点的节点。
示例 1:
输入:root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22
输出:[[5,4,11,2],[5,8,4,5]]
示例 2:
输入:root = [1,2,3], targetSum = 5
输出:[]
示例 3:
输入:root = [1,2], targetSum = 0
输出:[]
提示:
- 树中节点总数在范围
[0, 5000]
内 -1000 <= Node.val <= 1000
-1000 <= targetSum <= 1000
代码
/*
* @lc app=leetcode.cn id=113 lang=cpp
*
* [113] 路径总和 II
*/
// @lc code=start
/**
* 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 {
private:
vector<vector<int>> res;
vector<int> path;
void traverse(TreeNode* node, int count)
{
if(node->left == nullptr && node->right == nullptr && count == 0)
{
res.push_back(path);
return;
}
if(node->left == nullptr && node->right == nullptr)
return;
if(node->left != nullptr)
{
path.push_back(node->left->val);
//隐藏了回溯
traverse(node->left, count - node->left->val);
path.pop_back();//回溯
}
if(node->right != nullptr)
{
path.push_back(node->right->val);
//隐藏了回溯
traverse(node->right, count - node->right->val);
//回溯
path.pop_back();
}
return;
}
public:
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
res.clear();
path.clear();
if(root == nullptr)
return res;
//最开始忘记把根节点放入path中了,要注意
path.push_back(root->val);
traverse(root, targetSum - root->val);
return res;
}
};
// @lc code=end
106.从中序与后序遍历序列构造二叉树
代码随想录地址:https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E%84%E9%80%A0%E4%BA%8C%E5%8F%89%E6%A0%91.html
题目
给定两个整数数组 inorder
和 postorder
,其中 inorder
是二叉树的中序遍历, postorder
是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。
示例 1:
输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]
示例 2:
输入:inorder = [-1], postorder = [-1]
输出:[-1]
提示:
1 <= inorder.length <= 3000
postorder.length == inorder.length
-3000 <= inorder[i], postorder[i] <= 3000
inorder
和postorder
都由 不同 的值组成postorder
中每一个值都在inorder
中inorder
保证是树的中序遍历postorder
保证是树的后序遍历
代码
/*
* @lc app=leetcode.cn id=106 lang=cpp
*
* [106] 从中序与后序遍历序列构造二叉树
*/
// @lc code=start
/**
* 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 {
private:
TreeNode* traverse(vector<int>& inorder, int inbegin, vector<int>& postorder, int postbegin, int size)
{
if(size == 0)
return nullptr;
//对于后序遍历找到最后一个元素,它就是根节点
TreeNode* res = new TreeNode(postorder[postbegin + size - 1]);
//找到中序中的根节点
int index = 0;
while(inorder[inbegin + index] != res->val)
index++;
res->left = traverse(inorder, inbegin, postorder, postbegin, index);
res->right = traverse(inorder, inbegin + index + 1, postorder, postbegin + index, size - index - 1);
return res;
}
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
return traverse(inorder, 0, postorder, 0, inorder.size());
}
};
// @lc code=end
105.从前序与中序遍历序列构造二叉树
代码随想录地址:https://programmercarl.com/0106.%E4%BB%8E%E4%B8%AD%E5%BA%8F%E4%B8%8E%E5%90%8E%E5%BA%8F%E9%81%8D%E5%8E%86%E5%BA%8F%E5%88%97%E6%9E%84%E9%80%A0%E4%BA%8C%E5%8F%89%E6%A0%91.html
题目
给定两个整数数组 preorder
和 inorder
,其中 preorder
是二叉树的先序遍历, inorder
是同一棵树的中序遍历,请构造二叉树并返回其根节点。
示例 1:
输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]
示例 2:
输入: preorder = [-1], inorder = [-1]
输出: [-1]
提示:
1 <= preorder.length <= 3000
inorder.length == preorder.length
-3000 <= preorder[i], inorder[i] <= 3000
preorder
和inorder
均 无重复 元素inorder
均出现在preorder
preorder
保证 为二叉树的前序遍历序列inorder
保证 为二叉树的中序遍历序列
代码
/*
* @lc app=leetcode.cn id=105 lang=cpp
*
* [105] 从前序与中序遍历序列构造二叉树
*/
// @lc code=start
/**
* 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 {
private:
TreeNode* traverse(vector<int>& preorder, int prebegin, vector<int>& inorder, int inbegin, int size)
{
if(size == 0)
return nullptr;
//找到前序遍历的第一个元素,该元素即为根节点
TreeNode* res = new TreeNode(preorder[prebegin]);
//切割中序
int index = 0;
while(inorder[inbegin + index] != res->val)
index++;
res->left = traverse(preorder, prebegin + 1, inorder, inbegin, index);
res->right = traverse(preorder, prebegin + 1 + index, inorder, inbegin + index + 1, size - index - 1);
return res;
}
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return traverse(preorder, 0, inorder, 0, preorder.size());
}
};
// @lc code=end