代码随想录刷题随记16 -二叉树5

代码随想录刷题随记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]。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值