文档讲解:找树左下角的值 路径总和 从中序与后序遍历序列构造二叉树
题目链接:https://leetcode.cn/problems/find-bottom-left-tree-value/description/
思路:
本题要求我们找到树最深一层的最左节点的值。搜索的话复杂度应该会高,判断条件也不好写。所以这题很明显使用迭代法进行层序遍历,每层记录最左节点(即第一个节点)的值即可。迭代完成后自然记录的是最深一层的最左节点值。
核心代码:
/**
* 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 q;
int ans;
if(root) q.push(root);
while(!q.empty()){
TreeNode* cur;
int n=q.size();
cur=q.front();
ans=cur->val;
while(n--){
cur=q.front();
q.pop();
if(cur->left) q.push(cur->left);
if(cur->right) q.push(cur->right);
}
}
return ans;
}
};
题目链接:https://leetcode.cn/problems/path-sum/description/
思路:
本题要求我们判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum
。
那我们从根节点向下搜索即可,记录到当前节点的总和值,处理到叶子节点时,判断这个值是否等于targetSum即可,或者初始值设为-targetSum,每搜索到一个节点就把值加进去,到达叶子节点时判断总和是否为0即可。最后不要忘记回溯。
核心代码:
/**
* 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 dfs(TreeNode* cur,int sum){
if(!cur->left&&!cur->right){
if(sum==0) return true;
else return false;
}
if(cur->left&&dfs(cur->left,sum+cur->left->val)) return true;
if(cur->right&&dfs(cur->right,sum+cur->right->val)) return true;
return false;
}
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(!root) return false;
return dfs(root,-1*targetSum+root->val);
}
};
题目链接:https://leetcode.cn/problems/path-sum-ii/
思路:
本题与上题进行深搜的方式和逻辑一模一样,唯一需要注意的地方是本题需要记录路径,开一个path记录即可,path可以是全局变量,也可以传参,最后判断路径的sum等于targetSum时把记录的路径加到答案数组就可以了。
核心代码:
/**
* 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> ans;
void dfs(TreeNode* cur,int sum,vector& path){
if(!cur->left&&!cur->right){
if(!sum) ans.push_back(path);
return;
}
if(cur->left){
path.push_back(cur->left->val);
dfs(cur->left,sum+cur->left->val,path);
path.pop_back();
}
if(cur->right){
path.push_back(cur->right->val);
dfs(cur->right,sum+cur->right->val,path);
path.pop_back();
}
return ;
}
public:
vector> pathSum(TreeNode* root, int targetSum) {
vector path;
if(root) path.push_back(root->val);
if(root) dfs(root,root->val-targetSum,path);
return ans;
}
};
题目链接:https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/
思路:
首先我们要意识到一件事,中序为左中右,后序为左右中。下面我们分三步走:
1.因此我们可以知道,后序遍历序列的最后一个点,就是根节点。
2.查找根节点这个值在中序序列的位置,我们可以以此为分割得到左右两个序列。左边对应的是根节点左边子树的中序遍历序列,右边对应的是根节点右边子树的中序序列。知道左右子树的中序序列,我们也就知道了他们的大小。
3.由左右子树的大小,我们再来分割后序序列,后序序列的前一部分和左子树序列长度相同的序列,就是左子树的后序遍历序列。后面一部分去掉最后一个点则是右子树的后序序列。
到上面一步我们发现一件事情,我们得到了根节点,和左右子树分别的中序和后序序列。我们发现第一步就是根据中序后序来构造。因此我们对左右子树重复这三步即可。不断的迭代重复,直到子树剩下一个点,那就是叶子节点了,我们开始一步步回溯,把每个子树的根节点回溯到上一层,那就是上一层的左右子节点。
回溯到最后,我们得到的就是根节点,并且树也建好了。
核心代码:
/**
* 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* travelsal(vector& inorder,vector& postorder){
if(!postorder.size()) return NULL;
int midval=postorder[postorder.size()-1];
TreeNode* cur=new TreeNode(midval);
if(postorder.size()==1) return cur;
int mid;
for(mid=0;mid leftinorder(inorder.begin(),inorder.begin()+mid);
vector rightinorder(inorder.begin()+mid+1,inorder.end());
postorder.pop_back();
vector leftpost(postorder.begin(),postorder.begin()+leftinorder.size());
vector rightpost(postorder.begin()+leftinorder.size(),postorder.end());
cur->left=travelsal(leftinorder,leftpost);
cur->right=travelsal(rightinorder,rightpost);
return cur;
}
public:
TreeNode* buildTree(vector& inorder, vector& postorder) {
return travelsal(inorder,postorder);
}
};
题目链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/
思路:
会了上一道题就会这一道,本题与上题的处理方式和逻辑基本一致。唯一的区别是后序换成了前序,前序为中左右,因此我们的前序序列的第一个点为树的根节点,切割序列时注意这一点即可。
核心代码:
/**
* 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* travelsal(vector& preorder,vector& inorder){
if(!preorder.size()) return NULL;
int curval=preorder[0];
TreeNode* cur=new TreeNode(curval);
int curplace;
for(curplace=0;curplace leftin(inorder.begin(),inorder.begin()+curplace);
vector rightin(inorder.begin()+curplace+1,inorder.end());
preorder.erase(preorder.begin());
vector leftpre(preorder.begin(),preorder.begin()+leftin.size());
vector rightpre(preorder.begin()+leftin.size(),preorder.end());
cur->left=travelsal(leftpre,leftin);
cur->right=travelsal(rightpre,rightin);
return cur;
}
public:
TreeNode* buildTree(vector& preorder, vector& inorder) {
return travelsal(preorder,inorder);
}
};
今日学习时长4h,题目不算难。
剩下时间查论文看论文准备开题。