513. 找树左下角的值
第一想法:感觉用层序遍历比用递归遍历容易很多,层序遍历好久没写了,先试试。只会写遍历模板,其余的不太会写了...
看完想法:层序遍历还是复习一下。在que.push(root)前,先验证一下root是否为空。并用一个vector<vector<int>> vec 和 vector<int> tmp分别存储层序遍历后的二叉树和每层的二叉树。按照模板更改的话,只需要记录每行的第一个元素就可以了,到最后就会覆盖成最后一行的第一个的。在往深层遍历时,应该选用记录front的变量去递归,而不是root
递归想法:建立两个全局变量,一个存储最大深度,一个存储最大深度的最大值,然后使用回溯
//层序遍历法
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
if(root != nullptr) que.push(root);
int result = 0;
while(!que.empty()){
int size = que.size();//每层的大小是不一样的
for(int i = 0; i< size; i++){
TreeNode* tmp = que.front();
que.pop();
if(i == 0 ) result = tmp->val;
if(tmp->left) que.push(tmp->left);
if(tmp->right) que.push(tmp->right);
}
}
return result;
}
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) {
depth++;
traversal(root->left, depth);
depth--; // 回溯
}
if (root->right) {
depth++;
traversal(root->right, depth);
depth--; // 回溯
}
return;
}
int findBottomLeftValue(TreeNode* root) {
traversal(root, 0);
return result;
}
};
路径总和
第一想法:使用回溯,设置两个全局变量,用来存储bool和每次路径上的总和,但是好像有一种情况报错了
看完想法:注意,设置的全局变量不能成为局部函数的形参,这样会有歧义!正确做法是,当作一个变量就行;在回溯时,加入的应该是下一个即将要遍历的元素,即root->left->val而不是当前的元素值。
if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
if (!cur->left && !cur->right) return false; // 遇到叶子节点直接返回
在回溯中,遇到合适的路径要及时返回,如这里就是if(traversal) return true;
在路径搜索Ⅱ中,由于不需要对返回值作处理,所以递归函数的返回值是void
vector<vector<int>> result;
vector<int> path;
void traversal(TreeNode* root, int count){
if(!root->left && !root->right && count==0){
result.push_back(path);
}
if(!root->left && !root->right) return ;
if(root->left){
count-=root->left->val;
path.push_back(root->left->val);
traversal(root->left, count);
count+=root->left->val;
path.pop_back();
}
if(root->right){
count-=root->right->val;
path.push_back(root->right->val);
traversal(root->right, count);
count+=root->right->val;
path.pop_back();
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(root==nullptr) return result;
path.push_back(root->val);
traversal(root, targetSum-root->val);
return result;
}
106. 从中序与后序遍历序列构造二叉树
第一想法:切割中序数组使用后序的最后一个元素,不难。重点是如何切割后序数组,但不会...
看完想法:关键是,中序数组的大小和后续数组是相同的,因此可以以左中序数组大小来切割。剩下的就是正常递归勒。在递归的时候,使用root->left, right接收,因为递归函数从后序数组的左右子列中取元素作为节点。
这道题目使用for循环遍历来获取后序节点的下标,不好用find(),因为需要有<algorithem>头文件
定义vector的时候,利用begin(), end(), 等指针,直接使用括号
TreeNode* traversal(vector<int>& inorder, vector<int>& postorder){
if(postorder.size()==0) return nullptr;
// 后序遍历数组最后一个元素,就是当前的中间节点
int rootValue = postorder[postorder.size() - 1];
TreeNode* root = new TreeNode(rootValue);
// 叶子节点
if (postorder.size() == 1) return root;
//取postorder最后一个加入树中
int value_index=0;
for(; value_index<inorder.size(); value_index++){
if(inorder[value_index]==rootValue) break;
}
//在C++中,这种fuction(a:b)的形式是左闭右开,即[a, b)]
vector<int> left_inorder(inorder.begin(), inorder.begin()+value_index);
vector<int> right_inorder(inorder.begin()+value_index+1, inorder.end());
//删除后序最后一个
postorder.resize(postorder.size()-1);
//处理后序
vector<int> left_postorder(postorder.begin(), postorder.begin()+left_inorder.size());
vector<int> right_postorder(postorder.begin()+left_inorder.size(), postorder.end());
//递归逻辑
root->left = traversal(left_inorder, left_postorder);
root->right = traversal(right_inorder, right_postorder);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
//如果为大小为1,直接返回Null就行
if(inorder.size()==0) return nullptr;
return traversal(inorder, postorder);
}
105. 从中序与前序遍历序列构造二叉树
第一想法:如果使用erase删除vector元素值的话,erase的输入为指针,指向要删除元素的值
TreeNode* traversal(vector<int>& preorder, vector<int>& inorder){
//终止条件,如果preoder为0,返回
if(preorder.size()==0) return nullptr;
int rootvalue = preorder[0];
TreeNode* root = new TreeNode(rootvalue);
//叶子节点
if(preorder.size()==1) return root;
int value_index = 0;
for(; value_index<inorder.size(); value_index++){
if(inorder[value_index]==rootvalue) break;
}
//切割
vector<int> left_inorder(inorder.begin(), inorder.begin() + value_index);
vector<int> right_inorder(inorder.begin() +value_index+1, inorder.end());
preorder.erase(preorder.begin());
vector<int> left_preorder(preorder.begin(), preorder.begin() + left_inorder.size());
vector<int> right_preorder(preorder.begin()+ left_inorder.size(), preorder.end() );
root->left = traversal(left_preorder, left_inorder);
root->right = traversal(right_preorder, right_inorder);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
return traversal(preorder, inorder);
}