文档讲解:找树左下角的值 路径总和 从中序与后序遍历序列构造二叉树
513.找树左下角的值
题目链接: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<TreeNode*> 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;}
};
112.路径总和
题目链接: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);}
};
113.路径总和II
题目链接: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<vector<int>> ans;void dfs(TreeNode* cur,int sum,vector<int>& 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<vector<int>> pathSum(TreeNode* root, int targetSum) {vector<int> path;if(root) path.push_back(root->val);if(root) dfs(root,root->val-targetSum,path);return ans;}
};
106.从中序与后序遍历序列构造二叉树
题目链接: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<int>& inorder,vector<int>& 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<inorder.size();mid++)if(inorder[mid]==midval) break;vector<int> leftinorder(inorder.begin(),inorder.begin()+mid);vector<int> rightinorder(inorder.begin()+mid+1,inorder.end());postorder.pop_back();vector<int> leftpost(postorder.begin(),postorder.begin()+leftinorder.size());vector<int> rightpost(postorder.begin()+leftinorder.size(),postorder.end());cur->left=travelsal(leftinorder,leftpost);cur->right=travelsal(rightinorder,rightpost);return cur;}
public:TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {return travelsal(inorder,postorder);}
};
105.从前序与中序遍历序列构造二叉树
题目链接: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<int>& preorder,vector<int>& inorder){if(!preorder.size()) return NULL;int curval=preorder[0];TreeNode* cur=new TreeNode(curval);int curplace;for(curplace=0;curplace<inorder.size();curplace++)if(inorder[curplace]==curval) break;vector<int> leftin(inorder.begin(),inorder.begin()+curplace);vector<int> rightin(inorder.begin()+curplace+1,inorder.end());preorder.erase(preorder.begin());vector<int> leftpre(preorder.begin(),preorder.begin()+leftin.size());vector<int> rightpre(preorder.begin()+leftin.size(),preorder.end());cur->left=travelsal(leftpre,leftin);cur->right=travelsal(rightpre,rightin);return cur;}
public:TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {return travelsal(preorder,inorder);}
};
今日总结
今日学习时长4h,题目不算难。
剩下时间查论文看论文准备开题。