找树左下角的值 leetcode 513
解法一:递归
class Solution {
public:
int MaxDepth=INT_MIN;
int res;
int traversal(TreeNode* node,int depth){
if(!node->left&&!node->right){
if(depth>MaxDepth){
MaxDepth=depth;
res=node->val;
}
}
if(node->left){
depth++;
traversal(node->left,depth);
depth--;
}
if(node->right){
depth++;
traversal(node->right,depth);
depth--;
}
return res;
}
int findBottomLeftValue(TreeNode* root) {
int dep=0;
return traversal(root,dep);
}
};
总结
1.不用对根节点进行操作,所以前后中序都可以,只要先左就行。
2.递归需要传入的参数是根节点和当前节点的深度,递归结束的条件是当前节点的左右孩子都为空则更新深度更新res,单层递归需要做的就是遍历当前节点的左右孩子,前提是左右孩子不为空(这样就不用判断根节点是否为空了)。
3.其中单层递归对孩子节点处理时代码可以更精简:
if(node->left){
traversal(node->left,depth+1);
}
将回溯的过程隐藏,因为此时调用递归函数传深度时是值传递,我们直接传入depth+1,不会改变depth的值。
解法二:层序迭代
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> que;
int res=0;
if(root!=nullptr) que.push(root);
while(!que.empty()){
int size=que.size();
for(int i=0;i<size;i++){
TreeNode* cur=que.front();
que.pop();
if(i==0) res=cur->val;
if(cur->left) que.push(cur->left);
if(cur->right) que.push(cur->right);
}
}
return res;
}
};
层序遍历记录每一层的第一个元素,通过迭代更新,就可以得到最后一行最左边的元素。
路径之和 leetcode 112
解法一:递归
class Solution {
public:
bool traversal(TreeNode* node,int count){
if(!node->left&&!node->right&&count==0) return true;
if(!node->left&&!node->right&&count!=0) return false;
if(node->left){
count-=node->left->val;
if(traversal(node->left,count)) return true;
count+=node->left->val;
}
if(node->right){
count-=node->right->val;
if(traversal(node->right,count)) return true;
count+=node->right->val;
}
return false;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==nullptr) return false;
return traversal(root,targetSum-root->val);
}
};
总结
1.递归传入的参数是当前遍历节点和一个计数变量,递归结束条件是遍历到叶子节点如果计数器为0返回true不为0返回false。
2.因为递归一进来没有判断当前节点是否为空,所以在遍历左右孩子时需要加一个是否为空的判断。
3.主函数hasPathSum中调用递归时需要传入的是target-root->val而不是target,因为单层递归里面减去的是左右孩子的值,没有对根节点进行操作。
4.和上一题513同理遍历左右孩子时回溯可以隐藏。
if(node->left){
if(traversal(node->left,count-node->left->val)) return true;
}
解法二:迭代
class Solution {
public:
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==nullptr) return false;
stack<pair<TreeNode*,int>> st;
st.push(pair<TreeNode*,int>(root,root->val));
while(!st.empty()){
pair<TreeNode*,int> node=st.top();
st.pop();
if(!node.first->left&&!node.first->right&&node.second==targetSum) return true;
if(node.first->left) st.push(pair<TreeNode*,int>(node.first->left,node.second+node.first->left->val));
if(node.first->right) st.push(pair<TreeNode*,int>(node.first->right,node.second+node.first->right->val));
}
return false;
}
};
从中序与后序遍历序列构造二叉树 leetcode 106
第一步:如果后序或者中序数组大小为零,说明是空节点直接返回NULL;
第二步:如果不为空,找后序的最后一个元素作为根节点,如果后序大小为1,则说明是叶子节点直接返回此节点;
第三步:如果不是叶子节点,找到后序数组最后一个元素在中序数组中的位置切割中序数组,切成左中序数组和右中序数组;
第四步:使用上一步得到的左中序数组的大小切割后序数组,切成左后序数组和右后序数组;
第五步:递归处理根节点元素的左子树和右子树。
class Solution {
public:
TreeNode* traversal(vector<int>& inorder,vector<int>& postorder){
if(inorder.size()==0) return nullptr;
int rootValue=postorder[postorder.size()-1];
TreeNode* rV=new TreeNode(rootValue);
if(postorder.size()==1) return rV;
int index=0;
for(index;index<inorder.size();index++){
if(inorder[index]==rootValue) break;
}
vector<int> leftinoeder(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()+leftinoeder.size());
vector<int> rightpostorder(postorder.begin()+leftinoeder.size(),postorder.end());
rV->left=traversal(leftinoeder,leftpostorder);
rV->right=traversal(rightinorder,rightpostorder);
return rV;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.size()==0) return nullptr;
return traversal(inorder,postorder);
}
};
总结
1.分隔区间时采用左开右闭的原则,vector数组容器在使用迭代器定义区间时遵循左闭右开原则。
2.在调用递归对根节点的左右孩子进行赋值时,不用判断rV->left是否为空。
从前序与中序遍历序列构造二叉树 leetcode 105
class Solution {
public:
TreeNode* traversal(vector<int>& preorder,int preorderbegin,int preorderend,
vector<int>& inorder,int inorderbegin,int inorderend){
if(preorderbegin==preorderend) return nullptr;
int rootValue=preorder[preorderbegin];
TreeNode* rV=new TreeNode(rootValue);
if(preorder.size()==1) return rV;
int index=0;
for(index;index<inorder.size();index++){
if(inorder[index]==rootValue) break;
}
//切割中序数组
int lfetinorder_begin=inorderbegin;
int lfetinorder_end=index;
int rightinorder_begin=index+1;
int rightinorder_end=inorderend;
//切割前序数组
int leftpreorder_begin=preorderbegin+1;
int leftpreorder_end=preorderbegin+1+index-inorderbegin;
int rightpreorder_begin=preorderbegin+1+index-inorderbegin;
int rightpreorder_end=preorderend;
rV->left=traversal(preorder,leftpreorder_begin,leftpreorder_end,
inorder,lfetinorder_begin,lfetinorder_end);
rV->right=traversal(preorder,rightpreorder_begin,rightpreorder_end,
inorder,rightinorder_begin,rightinorder_end);
return rV;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0||inorder.size()==0) return nullptr;
return traversal(preorder,0,preorder.size(),inorder,0,inorder.size());
}
};