513.找树左下角的值
递归法:
因为本题没有中间结点的处理逻辑,使用前序、中序、后序遍历均可(保证先处理左,再处理右即可)。
- 确定递归函数参数和返回值
参数有要遍历的树的根节点,还有一个int型变量来记录最长深度,返回值类型为void。
- 确定终止条件
当遇到叶子节点时,比较当前深度与最大深度,更新最大深度和左下角的值。
- 确定单层递归逻辑
递归过程要回溯,先递归左子树,再递归右子树
class Solution {
public:
int maxDepth=INT_MIN;
int result;
void find(TreeNode* p,int depth){
if(!p->left&&!p->right){
if(depth>maxDepth){
maxDepth=depth;
result=p->val;
}
}
if(p->left){
depth++;
find(p->left,depth);
depth--;
}
if(p->right){
depth++;
find(p->right,depth);
depth--;
}
}
int findBottomLeftValue(TreeNode* root) {
find(root,0);
return result;
}
};
迭代法:
迭代法更加简单,使用层序遍历,需要先将右孩子放入,再将左孩子放入,这样保证每一层都是从右往左遍历,最后一个元素即是最后一层最左边的元素。
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> qu;
qu.push(root);
TreeNode* node;
while(!qu.empty()){
node=qu.front();
qu.pop();
if(node->right) qu.push(node->right);
if(node->left) qu.push(node->left);
}
return node->val;
}
};
112. 路径总和
递归思路:如果是一棵空树,直接返回false;如果当前结点是叶子结点,需要判断从头结点到该叶子结点的和是否等于targetSum
,若等于返回true,否则返回false;单层执行逻辑为,递归遍历左子树和右子树,找到就返回true,遍历完还没有找到,说明不存在,返回false。
class Solution {
public:
int sum=0;
bool hasPathSum(TreeNode* root, int targetSum) {
if(!root) return false;
if(!root->left&&!root->right){
if(sum+root->val==targetSum) return true;
else return false;
}
if(root->left){
sum+=root->val;
if(hasPathSum(root->left,targetSum)) return true;
sum-=root->val;
}
if(root->right){
sum+=root->val;
if(hasPathSum(root->right,targetSum)) return true;
sum-=root->val;
}
return false;
}
};
113.路径总和ii
这道题目也顺便做了,与112思路基本一样,只不过113还要回溯数组里的元素。
class Solution {
public:
int sum=0;
vector<vector<int>> res;
void findPath(TreeNode* p,int targetSum,vector<int>& vec){
if(!p) return;
if(!p->left&&!p->right){
if(sum+p->val==targetSum){
vec.push_back(p->val);
res.push_back(vec);
vec.pop_back();
}
return;
}
if(p->left){
vec.push_back(p->val);
sum+=p->val;
findPath(p->left,targetSum,vec);
sum-=p->val;
vec.pop_back();
}
if(p->right){
vec.push_back(p->val);
sum+=p->val;
findPath(p->right,targetSum,vec);
sum-=p->val;
vec.pop_back();
}
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<int> vec;
findPath(root,targetSum,vec);
return res;
}
};
106.从中序与后序遍历序列构造二叉树
中序:左中右;后序:左右中
后序遍历的最后一个元素一定是中间元素,再根据这个中间元素值去找到中序遍历里面对应的位置,那么位置左边就是左子树,右边就是右子树;将中序数组切割为左中序和右中序两个数组(左闭右开),再根据左中序的元素个数去将后序数组切割为左后序和右后序(左闭右开),递归调用左中序和左后序找到当前结点的左孩子,递归调用右中序和右后序找到当前结点的右孩子。
注意: 切割数组时一定要严格遵循左闭右开的原则,否则一定会乱。中序数组切割时,区间为[0,index)、[index+1,end);后序数组切割时,区间为[0,leftInorder.size)、[leftInorder.size,end)—>这里要提前去除最后一个元素。
class Solution {
public:
TreeNode* buildTree(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=0;
for(;index<inorder.size();index++){
if(inorder[index]==rootValue) break;
}
vector<int> leftInorder(inorder.begin(),inorder.begin()+index);
vector<int> rightInoder(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=buildTree(leftInorder,leftPostorder);
root->right=buildTree(rightInoder,rightPostorder);
return root;
}
};