代码随想录刷题随记16 -二叉树5
513.找树左下角的值
leetcode链接
在树的最后一行找到最左边的值。首先要是最后一行,然后是最左边的值。使用递归法,如何判断是最后一行:就是深度最大的叶子节点一定是最后一行。
注意height的回溯。要在遍历左右节点后对height进行减操作
class Solution {
public:
int maxheight;
void sub(TreeNode * root,int &height,int & val){
height++;
if(root->left==nullptr&&height>maxheight&&root->right==nullptr){
val=root->val;
maxheight=height;
return;
}
if(root->left!=nullptr){
sub(root->left,height,val);
height--;
}
if(root->right!=nullptr){
sub(root->right,height,val);
height--;
}
}
int findBottomLeftValue(TreeNode* root) {
int val=0;
int height=0;
maxheight=0;
sub(root,height,val);
return val;
}
};
迭代法
使用层次遍历可以很容易的解决这个问题
class Solution {
public:
int findBottomLeftValue(TreeNode* root) {
queue<TreeNode*> myqueue;
myqueue.push(root);
int ret=0;
while(!myqueue.empty()){
int size=myqueue.size();
for(int i=0;i<size;i++){
TreeNode * cur=myqueue.front();
myqueue.pop();
if(i==0){
ret=cur->val;
}
if(cur->left!=nullptr)
myqueue.push(cur->left);
if(cur->right!=nullptr)
myqueue.push(cur->right);
}
}
return ret;
}
};
112. 路径总和
leetcode链接
递归很简单:
class Solution {
public:
bool sub(TreeNode* root, int targetSum){
targetSum-=root->val;
if(targetSum==0&&root->left==nullptr&&root->right==nullptr){
return true;
}
bool left=false;
bool right=false;
if(root->left!=nullptr){
left=sub(root->left,targetSum);
}
if(root->right!=nullptr){
right=sub(root->right,targetSum);
}
return left||right;
}
bool hasPathSum(TreeNode* root, int targetSum) {
if(root==nullptr)
return false;
return sub(root,targetSum);
}
};
113. 路径总和ii
和上面的题类似的题目
leetcode链接
这道题与上面的题目的不同之处在于要返回的不是有没有这样一条路径,而是要记录并返回所有的路径
涉及回溯的思想,由于sub函数本身就自带回溯,所以left和right节点处不能重复回溯了,如下代码注释所示
解题代码:
class Solution {
public:
void sub(vector<vector<int>>& ret,TreeNode* root, int targetSum,vector<int> & path){
targetSum-=root->val;
path.push_back(root->val);
if(root->left==nullptr&&root->right==nullptr&&targetSum==0){
ret.push_back(path);
path.pop_back();
return;
}
if(root->left!=nullptr){
//path.push_back(root->left->val);
sub(ret,root->left,targetSum,path);
//path.pop_back();
}
if(root->right!=nullptr){
//path.push_back(root->right->val);
sub(ret,root->right,targetSum,path);
//path.pop_back();
}
path.pop_back();
}
vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
vector<vector<int>> ret;
vector<int> path;
if(root==nullptr)
return {};
sub(ret,root,targetSum,path);
return ret;
}
};
106.从中序与后序遍历序列构造二叉树
leetcode链接
递归
class Solution {
public:
TreeNode* sub(vector<int>& inorder, vector<int>& postorder,int endpost,int startpost,int endmid,int startmid){
TreeNode * root= new TreeNode(postorder[endpost]);
int index=startmid;
while(inorder[index]!=root->val&&index<=endmid)
index++;
int numleft=index-startmid;
//左树
if(numleft!=0)
root->left=sub(inorder,postorder,startpost+numleft-1,startpost,index-1,startmid);
//右树
int numright=endmid-index;
if(numright!=0)
root->right=sub(inorder,postorder,endpost-1,startpost+numleft,endmid,index+1);
return root;
}
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(inorder.size()==0)
return nullptr;
return sub(inorder,postorder,postorder.size()-1,0,inorder.size()-1,0);
}
};
105.从前序与中序遍历序列构造二叉树
leetcode链接
套路和从中序与后序中恢复树是一样的
class Solution {
public:
TreeNode* sub(vector<int>& preorder, vector<int>& inorder,int prestart,int preend,int midstart,int midend ){
TreeNode * root=new TreeNode(preorder[prestart]);
int index=midstart;
while(inorder[index]!=root->val&&index<=midend){
index++;
}
int leftnum=index-midstart;
if(leftnum!=0){
root->left=sub(preorder,inorder,prestart+1,prestart+leftnum,midstart,index-1);
}
int rightnum=midend-index;
if(rightnum!=0){
root->right=sub(preorder,inorder,prestart+ leftnum+1,preend,index+1,midend);
}
return root;
}
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0)
return nullptr;
return sub(preorder,inorder,0,preorder.size()-1,0,preorder.size()-1);
}
};
前序和中序可以唯一确定一棵二叉树。
后序和中序可以唯一确定一棵二叉树。
前序和后序不能唯一确定一棵二叉树,因为没有中序遍历无法确定左右部分
tree1 的前序遍历是[1 2 3], 后序遍历是[3 2 1]。
tree2 的前序遍历是[1 2 3], 后序遍历是[3 2 1]。