代码随想录算法训练营第二十一天 | 找树左下角的值、路径总和、从中序与后序遍历序列构造二叉树

找树左下角的值

题目链接/文章讲解/视频讲解: 代码随想录

解题思路

这里比较容易搞混的点就是:左下角的值是最深层最左侧的叶子节点,那其实三种遍历方式都是可以的,我们因为中节点不做处理,只需要去递归到左边的最底层,没有就去递归右节点的最底层即可

迭代法(比较简单,模版)

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
          queue<TreeNode*> que;
          que.push(root);
          int result;
        while(!que.empty())
        {
            int size = que.size();
            for(int i=0;i<size;i++)
            {
                TreeNode* node = que.front();
                que.pop();
                if(i==0){
                    result = node->val;
                }
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
             }
        }
        return result;
    }
};

递归法(含回溯) 

回溯就是让这一层递归前后的值不变

class Solution {
public:
    int result;
    int maxDepth = INT32_MIN;
    void travelSal(TreeNode* node , int depth)
    {
        if(node->left==nullptr && node->right==nullptr)
        {
            if(depth>maxDepth)   //如果是更深层的叶子节点则记录,如果不是就不做处理
            {
                maxDepth = depth;
                result = node->val;
            }
        }
        //不是叶子节点,则先遍历左,再遍历右,体现了左下角
        if(node->left) travelSal(node->left,depth+1);
        if(node->right) travelSal(node->right,depth+1);
    }
    
    int findBottomLeftValue(TreeNode* root) {
        travelSal(root,1);
        return result;
    }
};

路径总和

题目链接/文章讲解/视频讲解: 代码随想录

解题思路

这题还是比较简单的,我的思路使用中左右前序遍历,去寻找相加等于路径和的就可以,记得回溯

class Solution {
public:
    bool findSum(TreeNode* node, int targetSum)
    {
        if(node==nullptr) return false;
        if(node->left==nullptr && node->right == nullptr)    //遇到叶子节点,就判断路径和是否达到
        {
             if(targetSum- node->val ==0)  return true;
             else return false;
        }
        if(node->left) {
             targetSum-= node->val;
             if(findSum(node->left,targetSum)) return true;  //如果左孩子可以,收集信息返回父节点
             targetSum+= node->val;
        }
        if(node->right){
             targetSum -=node->val;
             if(findSum(node->right,targetSum)) return true;
             targetSum += node->val;
        }
        return false;
    }
    
    bool hasPathSum(TreeNode* root, int targetSum) {
            return findSum(root,targetSum);
    }
};

从中序与后序遍历序列构造二叉树

题目链接/文章讲解/视频讲解: 代码随想录

解题思路

后序遍历序列的最后一个元素一定是根节点,那么根据这个可以找到中序序列中和这个相等的索引下标,用去切割中序遍历序列,分为左区间和右区间,随后根据左区间和右区间再切割后序序列,然后递归左右区间即可·

切割中序比较简单,那切割后序呢?

我们只需要先用resize将最后一个元素舍弃后,用中序的左右区间的数量去切割即可,因为他们的数量必定是相同的。

注意:前序和中序也可以构造二叉树,但是前序和后序无法构造,因为不能将左右子树分开

class Solution {
public:
   TreeNode* travelSal(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 = travelSal(leftinorder,leftPostOrder);
        root->right = travelSal(rightinorder,rightPostOrder);
        return root;  //构造完了返回节点给上面接收
   }

    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
            return travelSal(inorder,postorder);
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值