5道题目
513. 找树左下角的值
112. 路径总和
113. 路径总和 II
105. 从前序与中序遍历序列构造二叉树
106. 从中序与后序遍历序列构造二叉树
解题理解
今天的题都挺难的,每道题只能说有一点思路,更别提实现了。
513
通过这题我明白了递归时什么时候需要对参数+1,其实+1就是回溯的过程,之前博客里的理解写的是不能确定该参数需不需要+1。
class Solution {
public:
int res;
int maxdepth = INT_MIN;
void traversal(TreeNode* node, int depth){
if(!node->left && !node->right){
if(maxdepth < depth){
maxdepth = depth;
res = node->val;
}
}
if(node->left){
depth ++;
traversal(node->left, depth);//traversal(node->left, depth + 1);
depth --;
}
if(node->right){
depth ++;
traversal(node->right, depth);//traversal(node->right, depth + 1);
depth --;
}
}
int findBottomLeftValue(TreeNode* root) {
if(root == nullptr) return 0;
traversal(root, 1);
return res;
}
};
112和113
这两道题是同种题,也是通过这两题稍微理解了一点什么时候递归需要设置返回值。
112中,是将叶子节点的true一个一个返上去,而且传入的参数是目标值-当前值这个过程很巧妙
113中我一直在思考vector.clear放在那里,没想到不需要在递归里设置clear,而且这道题需要回溯的不止sum,还有记录路径的vector。
// 112. 路径总和
class Solution {
public:
bool pathsum(TreeNode* node, int count){
if(!node->left && !node->right && count == 0) return true;
if(!node->left && !node->right) return false;
if(node->left){
count -= node->left->val;
if(pathsum(node->left, count)) return true;
count += node->left->val;
}
if(node->right){
count -= node->right->val;
if(pathsum(node->right, count)) return true;
count += node->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return false;
return pathsum(root, targetSum - root->val);
}
};
//113. 路径总和 II
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void traversal(TreeNode* node, int count){
if(!node->left && !node->right && count == 0){
res.push_back(path);
return;
}
if(!node->left && !node->right) return;
if(node->left){
path.push_back(node->left->val);
count -= node->left->val;
traversal(node->left, count);
count += node->left->val;
path.pop_back();
}
if(node->right){
path.push_back(node->right->val);
count -= node->right->val;
traversal(node->right, count);
count += node->right->val;
path.pop_back();
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
if(root == nullptr) return res;
path.push_back(root->val);
traversal(root, targetSum - root->val);
return res;
}
};
105和106
从两个遍历顺序确定一颗二叉树是个经典问题了,之前考研学数据结构有很深的印象,好像还记得不能从前序和后序遍历确定一颗二叉树,整体的流程我还记得,但是切割过程中,没想起来需要把已知(这两道题分别从前序和后序得到头节点,然后去前序与中序切割)的左(右)子树长度拿去前序或中序里切割。
然后106跟105的实现过程思想一致,但实现起来差别挺大,自己实现了一版实现过程完全一致的105,但时间和空间效率都很差。
//106. 从中序与后序遍历序列构造二叉树
class Solution {
public:
TreeNode* traversal(vector<int>& inorder, vector<int>& postorder){
if(postorder.size() == 0) return nullptr;
TreeNode* root = new TreeNode(postorder[postorder.size() - 1]);
if (postorder.size() == 1) return root;
int index;
for(index = 0; index < inorder.size(); index ++){
if(inorder[index] == root->val) break;
}
vector<int> leftinorder(inorder.begin(), inorder.begin() + index);
vector<int> rightinorder(inorder.begin() + index + 1, inorder.end());
postorder.resize(postorder.size() - 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;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.size() == 0 || postorder.size() == 0) return nullptr;
return traversal(inorder, postorder);
}
};
//105. 从前序与中序遍历序列构造二叉树
class Solution {
public:
TreeNode* traversal(vector<int>& preorder, vector<int>& inorder){
if(inorder.size() == 0) return nullptr;
TreeNode* root = new TreeNode(preorder[0]);
if(inorder.size() == 1) return root;
int index;
for(index = 0; index < inorder.size(); index ++){
if(inorder[index] == root->val) break;
}
vector<int> leftinorder(inorder.begin(), inorder.begin() + index);
vector<int> rightinorder(inorder.begin() + index + 1, inorder.end());
vector<int> newpreorder(preorder.begin() + 1, preorder.end());
vector<int> leftpreorder(newpreorder.begin(), newpreorder.begin() + leftinorder.size());
vector<int> rightpreorder(newpreorder.begin() + leftinorder.size(), newpreorder.end());
root->left = traversal(leftpreorder, leftinorder);
root->right = traversal(rightpreorder, rightinorder);
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size() == 0 || inorder.size() == 0) return nullptr;
return traversal(preorder, inorder);
}
};