513. 找树左下角的值
思想:这次用了迭代法,使用队列实现,按照根右左的顺序实现。最后出队的是树最深层最左边的值。递归的方法还没有掌握,应该是前序遍历然后如果碰到新的深度则替换原有的左下角值。
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
//迭代 广度优先遍历
queue<TreeNode*> que;
que.push(root);
vector<int> ans;
while(!que.empty()){
if(que.front()!=nullptr){
TreeNode* temp=que.front();
ans.push_back(temp->val);
if(temp->right!=nullptr)que.push(temp->right);
if(temp->left!=nullptr)que.push(temp->left);
que.pop();
}
}
return *(ans.end()-1);
}
};
112. 路径总和
思想:碰到左右孩子为空的节点就往定义的vector数组里存入一次和。这道题主要要注意的是回溯的思路,在什么时候加入val,在什么时候减去val。也可以不做改变,直接把变化写在函数的参数里也可以,这样做掩藏了回溯的过程。还有一个要注意的是,相比于访问到最后一个节点时检查sum是否等于target,直接把初始值设为target然后访问每一层都减去对应的val然后查看末尾值是否等于0,代码可以少些很多。
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
vector<int> ans;
int sum = 0;
tranversal(root,sum,ans);
for(int i=0;i<ans.size();i++){
if(ans[i]==targetSum) return true;
}
return false;
}
void tranversal(TreeNode* root, int& sum, vector<int>& ans){
if(root==nullptr) return;
sum+=root->val;
if(root->left==nullptr&&root->right==nullptr) ans.push_back(sum);
tranversal(root->left,sum,ans);
tranversal(root->right,sum,ans);
sum-=root->val;
}
};
113. 路径总和ii
思想:和112.路径总和i的思想一样,但是这次更明显地突出了回溯的使用。在到达叶子节点时如果发现最后的结果不等于目标值,则需要回退到上一层,在此之前我们要先把在这一层放进数组中的值pop_back出来。
class Solution {
public:
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<int> ans;
vector<vector<int>> res;
if(root==nullptr) return res;
ans.push_back(root->val);
targetSum-=root->val;
visit(root,targetSum,res,ans);
return res;
}
void visit(TreeNode* root, int targetSum, vector<vector<int>>& res, vector<int> ans){
if(root->left==nullptr&&root->right==nullptr&&targetSum==0){
res.push_back(ans);
}
if(root->left==nullptr&&root->right==nullptr){
return;
}
if(root->left){
ans.push_back(root->left->val);
int temp = targetSum-root->left->val;
visit(root->left,temp,res,ans);
ans.pop_back();
}
if(root->right){
ans.push_back(root->right->val);
int temp = targetSum-root->right->val;
visit(root->right,temp,res,ans);
ans.pop_back();
}
}
};
106.从中序与后序遍历序列构造二叉树
思想:首先要明确怎么才能找到根节点,后序遍历数组中的最后一个元素就是根节点,在我们找到这个值之后,我们设置index来记录这个根节点在中序遍历序列中的什么部位。由于根节点把这个数组分成了两段,分别是左子树和右子树,所以我们也要通过递归分开处理。确定了这些之后,我们可以建立新的左子树的后序遍历数组和中序遍历数组,以及新的右子树的后序遍历数组和中序遍历数组。在这里我们需要注意的是必须先找出中序遍历数组,因为我们并不知道在后续遍历序列中,两个子树的间隔在什么地方,只能通过index来找。
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
// 递归中止条件
if (postorder.size() == 0)
return nullptr;
TreeNode* root = new TreeNode;
if (postorder.size() == 1){
root->val = postorder[postorder.size() - 1];
return root;
}
// 找到分开左右孩子的根节点的下标
int index;
for (index = 0; index < inorder.size(); index++) {
if (inorder[index] == postorder[postorder.size() - 1])
break;
}
root->val = postorder[postorder.size() - 1];
// 新的中序遍历数组
vector<int> new_inorder1(inorder.begin(), inorder.begin() + index);
vector<int> new_inorder2(inorder.begin() + index + 1, inorder.end());
// 新的后序遍历数组
vector<int> new_postorder1(postorder.begin(), postorder.begin() + index);
vector<int> new_postorder2(postorder.begin() + index, postorder.end() - 1);
// 左右孩子
root->left = buildTree(new_inorder1,new_postorder1);
root->right = buildTree(new_inorder2,new_postorder2);
return root;
// 先找后序遍历的根节点
//
}
};
105.从前序与中序遍历序列构造二叉树
思想:同前一题,注意还是先分割中序遍历数组再分割前序遍历数组,创建新数组时要注意边界的把控.
class Solution {
public:
TreeNode* buildTree( vector<int>& preorder, vector<int>& inorder) {
// 递归中止条件
if (preorder.size() == 0)
return nullptr;
TreeNode* root = new TreeNode;
if (preorder.size() == 1){
root->val = preorder[preorder.size() - 1];
return root;
}
// 找到分开左右孩子的根节点的下标
int index;
for (index = 0; index < inorder.size(); index++) {
if (inorder[index] == preorder[0])
break;
}
root->val = preorder[0];
// 新的中序遍历数组
vector<int> new_inorder1(inorder.begin(), inorder.begin() + index);
vector<int> new_inorder2(inorder.begin() + index + 1, inorder.end());
// 新的前序遍历数组
vector<int> new_preorder1(preorder.begin()+1, preorder.begin() + index+1);
vector<int> new_preorder2(preorder.begin()+1 + index, preorder.end());
// 左右孩子
root->left = buildTree(new_preorder1, new_inorder1);
root->right = buildTree(new_preorder2, new_inorder2);
return root;
// 先找后序遍历的根节点
//
}
};