day 18 第六章 二叉树
今日内容
-
513.找树左下角的值
-
- 路径总和 113.路径总和ii
-
106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树
详细布置
找树左下角的值
本地递归偏难,反而迭代简单属于模板题, 两种方法掌握一下
题目链接/文章讲解/视频讲解:programmercarl.com/0513.%E6%89…
思路:
迭代法特别的简单,只要层次遍历整个二叉树,每次记录该层中最左边的元素即可。
递归法主要是确定某次遍历中。是否为最后一层,就需要用一个maxDeepth用于记录当前遍历的层数。
代码:
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
que.push(root);
int left = root->val;
while(!que.empty()){
int size = que.size();
for(int i=0;i<size;i++){
TreeNode* node = que.front();
que.pop();
if(i==0) left = node->val;
if(node->left) que.push(node->left);
if(node->right) que.push(node->right);
}
}
return left;
}
};
迭代法
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)
{
depth++;
traversal(root->right,depth);
depth--;
}
return;
}
int findBottomLeftValue(TreeNode* root) {
traversal(root,0);
return result;
}
};
路径总和
本题 又一次设计要回溯的过程,而且回溯的过程隐藏的还挺深,建议先看视频来理解
\112. 路径总和,和 113. 路径总和ii 一起做了。 优先掌握递归法。
题目链接/文章讲解/视频讲解:programmercarl.com/0112.%E8%B7…
思路: 递归遍历整个二叉树,记录当前路径各个节点的总和,注意回退时需要减掉当前节点的值,而在这里面回退有多种条件。
代码:
class Solution {
public:
int sum = 0;
int flag = 0;
void preTravser(TreeNode* root,int t){
if(!root) return;
sum += root->val;
if(!root->left&&!root->right){
if(sum == t)
{
flag=1;
}
sum-=root->val;
return;
}
if(root->left) preTravser(root->left,t);
if(root->right) preTravser(root->right,t);
sum-=root->val;
return;
}
bool hasPathSum(TreeNode* root, int targetSum) {
preTravser(root,targetSum);
return flag;
}
};
从中序与后序遍历序列构造二叉树
本题算是比较难的二叉树题目了,大家先看视频来理解。
106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树 一起做,思路一样的
题目链接/文章讲解/视频讲解:programmercarl.com/0106.%E4%BB…
思路: 左右递归切割字符串,注意区间左闭右开,以及抛弃的元素。
class Solution {
private:
TreeNode* traversal(vector<int>& inorder, vector<int>& postorder) {
if(!postorder.size()) return NULL;
// 后序遍历数组最后一个元素,就是当前的中间节点
int rootValue = postorder[postorder.size() - 1];
TreeNode* root = new TreeNode(rootValue);
// 叶子节点
if (postorder.size() == 1) return root;
// 找到中序遍历的切割点
int delimiterIndex;
for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {
if (inorder[delimiterIndex] == rootValue) break;
}
//切割中序数组 左闭右开
vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());
// postorder 舍弃末尾元素
postorder.resize(postorder.size() - 1);
//切割后序数组 左闭右开 注意与中序切割的思路不同 不需要+1 一个元素已经抛弃
vector<int> leftPostorder(postorder.begin(),postorder.begin()+leftInorder.size());
vector<int> rightPostorder(postorder.begin()+leftInorder.size(),postorder.end());
root->left = traversal(leftInorder, leftPostorder);
root->right = traversal(rightInorder, rightPostorder);
return root;
}
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0 || postorder.size() == 0) return NULL;
return traversal(inorder, postorder);
}
};