力扣第15天----第513题、第112、113题、第106、105题
文章目录
一、第513题–找树左下角的值
大概明白了吧,重点在于回溯的运用。这里采用后序遍历(前序遍历、中序遍历都可以)。定义几个全局变量,通过travesal函数不断递归遍历二叉树,去修改全局变量。
- 传入参数及返回值----要遍历的根节点,所处的深度。这里要用到了回溯,遍历的时候加1,遍历完了返回给上一层节点时,减1。
- 终止条件----当前root处于叶子节点就返回。返回前要修改maxdepth、result数值,如果当前节点depth大于maxdepth,maxdepth就+1;result就赋值为root的val。因为一层中只有最左侧会触发“当前节点depth大于maxdepth”条件,所以result就记录了最左侧的值。
- 单层递归逻辑----遍历左子树,遍历右子树,注意depth回溯。遍历子树完成后,要恢复原状,回到根节点状态,不能影响其他子树的遍历。
class Solution {
public:
int result;
int maxdepth = 1;
void travesal(TreeNode* root, int depth){
if (root->left == nullptr && root->right == nullptr){
if (depth > maxdepth){
result = root->val;
maxdepth = depth;
}
return;
}
if(root->left){
depth++;
travesal(root->left, depth);
depth--;
}
if (root->right){
depth++;
travesal(root->right, depth);
depth--;
}
}
int findBottomLeftValue(TreeNode* root) {
result = root->val;
travesal(root, 1);
return result;
}
};
二、第112、113题–路径总和
112题,采用后序遍历,其实对于中节点,没有处理。
- 传入参数及返回值—如果要维护全局变量,就要重新定义递归函数,有时候用全局变量会逻辑清晰、操作简单,譬如有vector这种不易操作的,就额外使用全局变量,再定义一个新函数。这道题不需要全局变量,不用重新定义函数。
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if (root == nullptr) return false;
if (root->left == nullptr && root->right == nullptr && root->val == targetSum) return true;
if (root->left == nullptr && root->right == nullptr && root->val != targetSum) return false;
if (hasPathSum(root->left, targetSum - root->val)) return true;
if (hasPathSum(root->right, targetSum - root->val)) return true;
return false;
}
};
113题,跟上面一道题,不太一样,费了点劲。
class Solution {
public:
vector<vector<int>> result;
vector<int> r;
void dfs(TreeNode* root, int targetSum){
if (root == nullptr) return ;
r.push_back(root->val);
if (root->left == nullptr && root->right == nullptr && root->val == targetSum){
result.push_back(r);
}
dfs(root->left, targetSum - root->val);
dfs(root->right, targetSum - root->val);
r.pop_back();
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
dfs(root, targetSum);
return result;
}
};
三、第106、105题-- 从中序与后序遍历序列构造二叉树
106题,实现时很麻烦,要很小心、很注意。思路:后序遍历找中节点,并建立跟节点root→前序遍历找中节点index→前序遍历拆分左右子树→后续遍历拆分左右子树(根据前序左子树的大小)→递归实现,左右子树的构建(返回子树的根节点)→root的left、right分别指向左右子树的根节点。
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if (inorder.size() == 0) return nullptr;
int center_val = postorder[postorder.size() - 1];
int center_index = 0;
for (int i = 0; i < inorder.size(); i++){
if (inorder[i] == center_val) center_index = i;
}
TreeNode* root = new TreeNode(center_val);
vector<int> inorder_left(inorder.begin() , inorder.begin() + center_index );
// for_each(inorder_left.begin(), inorder_left.end(), [](int i){cout <<i << ' ';});
// cout << endl;
vector<int> inorder_right(inorder.begin()+center_index+1 , inorder.end());
// for_each(inorder_right.begin(), inorder_right.end(), [](int i){cout <<i << ' ';});
// cout << endl;
vector<int> postorder_left(postorder.begin(), postorder.begin() + inorder_left.size());
// for_each(postorder_left.begin(), postorder_left.end(), [](int i){cout <<i << ' ';});
// cout << endl;
vector<int> postorder_right(postorder.begin() + inorder_left.size(), postorder.end() - 1);
// for_each(postorder_right.begin(), postorder_right.end(), [](int i){cout <<i << ' ';});
// cout << endl;
TreeNode* left = buildTree(inorder_left, postorder_left);
TreeNode* right = buildTree(inorder_right, postorder_right);
root->left = left;
root->right = right;
return root;
}
};
105题,跟106题,基本上一模一样的。
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (inorder.size() == 0) return nullptr;
int center_val = preorder[0];
int center_index = 0;
for (int i = 0; i < inorder.size(); i++){
if (inorder[i] == center_val) center_index = i;
}
TreeNode* root = new TreeNode(center_val);
vector<int> inorder_left(inorder.begin() , inorder.begin() + center_index );
//for_each(inorder_left.begin(), inorder_left.end(), [](int i){cout <<i << ' ';});
//cout << endl;
vector<int> inorder_right(inorder.begin()+center_index+1 , inorder.end());
//for_each(inorder_right.begin(), inorder_right.end(), [](int i){cout <<i << ' ';});
//cout << endl;
vector<int> preorder_left(preorder.begin()+1, preorder.begin() +1 +inorder_left.size());
// for_each(preorder_left.begin(), preorder_left.end(), [](int i){cout <<i << ' ';});
// cout << endl;
vector<int> preorder_right(preorder.begin() +1 +inorder_left.size(), preorder.end()) ;
// for_each(preorder_right.begin(), preorder_right.end(), [](int i){cout <<i << ' ';});
// cout << endl;
TreeNode* left = buildTree(preorder_left, inorder_left);
TreeNode* right = buildTree(preorder_right, inorder_right);
root->left = left;
root->right = right;
return root;
}
};