● 513.找树左下角的值
题目描述
假设二叉树中至少有一个节点。
示例 1:
输入: root = [2,1,3]
输出: 1
示例 2:
输入: [1,2,3,4,null,5,6,null,null,7]
输出: 7
提示:
- 二叉树的节点个数的范围是
[1,10<sup>4</sup>]
-2<sup>31</sup> <= Node.val <= 2<sup>31</sup> - 1
解题思路
层序遍历 (广域搜索算法)
这里注意加入队列的是先加入右子树,然后加入左子树
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
if(root)que.push(root);
int ans = INT_MIN;
while(!que.empty())
{
int size = que.size();
for(int i = 0; i< size; ++i)
{
TreeNode * node = que.front();
que.pop();
if(node->right)que.push(node->right);
if(node->left)que.push(node->left);
ans = node->val;
}
}
return ans;
}
};
递归
使用递归法,如何判断是最后一行呢,其实就是深度最大的叶子节点一定是最后一行。
前序:中左右
中序:左中右
后序:左右中
只要我们优先遍历左节点,
我们求的是最后一行的最左边的元素,而不是左孩子
递归三部曲:
确定递归函数的参数和返回值
int maxDepth = INT_MIN; // 全局变量 记录最大深度
int result; // 全局变量 最大深度最左节点的数值
void traversal(TreeNode* root, int depth)
确定终止条件;
if(node->left == nullptr && node->right == nullptr )
{
if(depth>maxDeep)
{
maxDeep =depth;
result = node->val;
}
}
return
单次递归的逻辑
depth++后在depth- -??
向左遍历,depth++ 回溯
?为何要回溯
if(node->left){
depth++;
traversal(node->left,depth);
depth--;
}
if(node->right)
{
depth++;
traversal(node->right,depth);
depth--;
}
代码整合
class Solution {
public:
int maxDeep = INT_MIN;
int result;
void traversal(TreeNode * node , int depth)
{
if(node->left == nullptr && node->right == nullptr )
{
if(depth>maxDeep)
{
maxDeep =depth;
result = node->val;
}
}
if(node->left){
depth++;
traversal(node->left,depth);
depth--;
}
if(node->right)
{
depth++;
traversal(node->right,depth);
depth--;
}
return;
}
int findBottomLeftValue(TreeNode* root) {
traversal(root,result);
return result;
}
};
● 112. 路径总和
题目描述
给你二叉树的根节点 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
解题思路
递归三部曲
确定递归函数的参数和返回类型
bool mysum(TreeNode* node, int targetSum)
确定终止条件
if(node!=nullptr&&node->left==nullptr&& node->right==nullptr)
{
if(targetSum == 0)
return true;
else
return false;
}
确定单次循环的逻辑
if(node&&node->left)
{
if(mysum(node->left,targetSum-node->left->val))
return true;
}
if(node&&node->right)
{
if(mysum(node->right,targetSum-node->right->val))
{
return true;
}
}
总体代码整合
class Solution {
public:
bool mysum(TreeNode* node, int targetSum)
{
if(node!=nullptr&&node->left==nullptr&& node->right==nullptr)
{
if(targetSum == 0)
return true;
else
return false;
}
if(node&&node->left)
{
if(mysum(node->left,targetSum-node->left->val))
return true;
}
if(node&&node->right)
{
if(mysum(node->right,targetSum-node->right->val))
{
return true;
}
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root) return mysum(root, targetSum-root->val);
return false;
}
};
113.路径总和ii
题目描述
给你二叉树的根节点 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
解题思路
class Solution {
public:
bool mysum(TreeNode* node, int targetSum)
{
if(node!=nullptr&&node->left==nullptr&& node->right==nullptr)
{
if(targetSum == 0)
return true;
else
return false;
}
if(node&&node->left)
{
if(mysum(node->left,targetSum-node->left->val))
return true;
}
if(node&&node->right)
{
if(mysum(node->right,targetSum-node->right->val))
{
return true;
}
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root) return mysum(root, targetSum-root->val);
return false;
}
};
● 106.从中序与后序遍历序列构造二叉树
题目描述
给定两个整数数组 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
保证是树的后序遍历
解题思路
/**
* 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:
TreeNode * traversal(vector<int> & inorder, vector<int>& postorder)
{
if(postorder.size()==0) return nullptr;
int rootval = postorder[postorder.size()-1];
TreeNode* root = new TreeNode(rootval);
if(postorder.size() == 1 )return root;
int index = 0;
for(index;index<inorder.size();index++)
{
if(inorder[index]==rootval)break;
}
//切割中序数组 切割为左中序数组,右中序数组
vector<int> leftmid(inorder.begin(),inorder.begin()+index);
vector<int> rightmid(inorder.begin()+index+1,inorder.end());
// postorder.resize(postorder.size() - 1);
//切后序数组,左后序数组,右后序数组
vector<int> leftpost(postorder.begin(),postorder.begin()+leftmid.size());
vector<int> rightpost(postorder.begin()+leftmid.size(),postorder.begin()+leftmid.size()+rightmid.size());
root->left = traversal(leftmid, leftpost);
root->right = traversal(rightmid, rightpost);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) return NULL;
// 参数坚持左闭右开的原则
return traversal(inorder, postorder);
}
};
105.从前序与中序遍历序列构造二叉树
题目描述
给定两个整数数组 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
保证 为二叉树的中序遍历序列
解题思路
/**
* 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:
TreeNode * traversal(vector<int>& preorder, vector<int>& inorder)
{
if(preorder.size() == 0) return nullptr;
int rootval = preorder[0];
TreeNode *root = new TreeNode(rootval);
if(preorder.size()==1)return root;
int index=0;
for(; index<inorder.size();++index)
{
if(inorder[index]==rootval)
break;
}
/// leftmid rightmid
vector<int> leftmid(inorder.begin(),inorder.begin()+index);
vector<int> rightmid(inorder.begin()+index+1,inorder.end());
//preleft, preright
vector<int> preleft(preorder.begin()+1,preorder.begin()+1+leftmid.size());
vector<int> preright(preorder.begin()+1+leftmid.size(),preorder.end());
// cout << "----------" << endl;
// cout<<"index "<<index<<endl;
// cout<<"rootval "<<rootval<<endl;
// cout<<"preright"<<endl;
// for(int i: preright)
// {
// cout<<i<<" ";
// }
// cout<<endl;
// cout<<"midright"<<endl;
// for(int i : rightmid)
// cout<<i;
// cout<<endl;
root->left = traversal(preleft,leftmid);
root->right = traversal(preright,rightmid);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (inorder.size() == 0 || preorder.size() == 0) return NULL;
return traversal(preorder,inorder);
}
};