Day18 二叉树第五天
LeetCode 513.找树左下角的值
本题没有对中间节点的处理,所以用前中后序都可以,但一定要注意回溯。
class Solution {
public:
int maxDepth=INT_MIN;
int res;
void traversal(TreeNode* root,int depth){
if(!root->left && !root->right){
if(depth>maxDepth){
maxDepth=depth;
res=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 res;
}
};
LeetCode 112.路径总和
与找二叉树路径的题相似,注意每一层的判断结果要向上一层返回。
这里注意空树的特判,还有根节点元素的值也要减掉。
class Solution {
public:
bool traversal(TreeNode*node,int cnt){
if(!node->left && !node->right && cnt==0)
return true;
if(!node->left && !node->right && cnt!=0)
return false;
if(node->left){
cnt-=node->left->val;
if(traversal(node->left,cnt)) return true;
cnt+=node->left->val;
}
if(node->right){
cnt-=node->right->val;
if(traversal(node->right,cnt)) return true;
cnt+=node->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(!root) return false;
return traversal(root,targetSum-root->val);
}
};
LeetCode 113.路径总和II
比上一题增加了要求,要把所有满足条件的路径全部输出。其实112题就是本题操作的一步,我们把上一题的终止条件改为向结果二维数组里加入路径即可,不仅如此,回溯部分的操作也变多了。
class Solution {
public:
vector<vector<int>> res;
vector<int> path;
void traversal(TreeNode* node,int cnt){
if(!node->left && !node->right && cnt==0){
res.push_back(path);
return;
}
if(!node->left && !node->right) return;
if(node->left){
path.push_back(node->left->val);
cnt-=node->left->val;
traversal(node->left,cnt);
cnt+=node->left->val;
path.pop_back();
}
if(node->right){
path.push_back(node->right->val);
cnt-=node->right->val;
traversal(node->right,cnt);
cnt+=node->right->val;
path.pop_back();
}
return;
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
res.clear();path.clear();
if(!root) return res;
path.push_back(root->val);
traversal(root,targetSum-root->val);
return res;
}
};
LeetCode 106.从中序与后序遍历序列构造二叉树
很复杂,坑点也很多的题。本题的关键在于根据中序数组中根节点的位置来把后序数组切割成两部分,这个有很多复杂的点。
中序左闭右开,要跳过根节点,所以下标要加1。
切割后序数组时,后序数组左半部分的长度正好等于中序数组的左半部分。
后序数组两部分是连着的,所以下标是相连的。
class Solution {
public:
TreeNode* traversal(vector<int>& inorder,vector<int>& postorder){
if(postorder.size()==0) return NULL;
int rootValue=postorder[postorder.size()-1];
TreeNode* root=new TreeNode(rootValue);
if(postorder.size()==1) return root;
int index;
for(index=0;index<inorder.size();index++)
if(inorder[index]==rootValue) 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 NULL;
return traversal(inorder,postorder);
}
};
LeetCode 105. 从前序与中序遍历序列构造二叉树
与106题方法一致,注意下标的操作。
class Solution {
private:
TreeNode* traversal (vector<int>& inorder, int inorderBegin, int inorderEnd, vector<int>& preorder, int preorderBegin, int preorderEnd) {
if (preorderBegin == preorderEnd) return NULL;
int rootValue = preorder[preorderBegin];
TreeNode* root = new TreeNode(rootValue);
if (preorderEnd - preorderBegin == 1) return root;
int delimiterIndex;
for (delimiterIndex = inorderBegin; delimiterIndex < inorderEnd; delimiterIndex++) {
if (inorder[delimiterIndex] == rootValue) break;
}
int leftInorderBegin = inorderBegin;
int leftInorderEnd = delimiterIndex;
int rightInorderBegin = delimiterIndex + 1;
int rightInorderEnd = inorderEnd;
int leftPreorderBegin = preorderBegin + 1;
int leftPreorderEnd = preorderBegin + 1 + delimiterIndex - inorderBegin;
int rightPreorderBegin = preorderBegin + 1 + (delimiterIndex - inorderBegin);
int rightPreorderEnd = preorderEnd;
root->left = traversal(inorder, leftInorderBegin, leftInorderEnd, preorder, leftPreorderBegin, leftPreorderEnd);
root->right = traversal(inorder, rightInorderBegin, rightInorderEnd, preorder, rightPreorderBegin, rightPreorderEnd);
return root;
}
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if (inorder.size() == 0 || preorder.size() == 0) return NULL;
// 参数坚持左闭右开的原则
return traversal(inorder, 0, inorder.size(), preorder, 0, preorder.size());
}
};
全是细节,好好总结。