代码随想录算法训练营第十六天|513.找树左下角的值,112. 路径总和,106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树

513. 找树左下角的值 - 力扣(LeetCode)

给定一个二叉树的 根节点 root,请找出该二叉树的 最底层 最左边 节点的值。

假设二叉树中至少有一个节点。

示例 1:

输入: root = [2,1,3]
输出: 1

思路:这里找左下角的值,要满足两个条件,一是最底层,二是最左边。

解决:采用层次遍历,最后一层的第一个数就是要找的数。

代码:

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        if(root!=NULL) que.push(root);
        int n;//每层的结果
        while(!que.empty()){
            int size=que.size();
            for(int i=0;i<size;i++){
                TreeNode* t=que.front();
                que.pop();
                if(i==0) n=t->val;//每层最左边的
                if(t->left) que.push(t->left);
                if(t->right) que.push(t->right);
            }
        }
        return n;
    }
};

106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

给定两个整数数组 inorder 和 postorder ,其中 inorder 是二叉树的中序遍历, postorder 是同一棵树的后序遍历,请你构造并返回这颗 二叉树 。

示例 1:

输入:inorder = [9,3,15,20,7], postorder = [9,15,7,20,3]
输出:[3,9,20,null,null,15,7]

思路:其实就是用代码模拟手动建树过程,一步一步还原手动步骤。

解决:分步骤解答:①判断数组为空;②利用后序数组最后元素分割中序数组,分为中序左数组和中序右数组;③再利用中序左数组和中序右数组分割后序数组,分为后序左数组和后序右数组;④递归步骤②。

注意:这里每次切割完中序数组后都要,舍去后序数组最后一个元素;中序分割和后序分割的区别,中序分割需要剔除后序数组最后元素,后序分割则不需要,根据中序左数组和中序右数组分割就行。

代码:

class Solution {
private:
    TreeNode* traversal (vector<int>& inorder, vector<int>& postorder){
        if(postorder.size()==0) return NULL;//第一步判空

        //第二步找到后序数组最后元素
        int rootg =postorder[postorder.size()-1];
        TreeNode* root=new TreeNode(rootg);//该节点作为父亲节点

        if(postorder.size()==1) return root;//最后遍历如果后序数组为就一个,说明是叶子节点,直接返回

        //第三步分割数组
        //先找到分割位置
        int n;
        for(n=0;n<inorder.size();n++){
            if(inorder[n]==rootg) break;//记录分割位置
        }
        //通过分割位置分割中序数组
        vector<int> leftinorder(inorder.begin(),inorder.begin()+n);//中序左数组
        vector<int> rightinorder(inorder.begin()+n+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=traversal(leftinorder,leftpostorder);
        root->right=traversal(rightinorder,rightpostorder);

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

        if (inorder.size() == 0 || postorder.size() == 0) return NULL;
        return traversal(inorder, postorder);

    }
};

105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。

示例 1:

输入: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7]
输出: [3,9,20,null,null,15,7]

思路:这里和上题类似,用前序和中序确定二叉树,前序是从前序数组第一个元素分割。

解决:同106

代码:

class Solution {
private:
    TreeNode* traversal (vector<int>& inorder, vector<int>& preorder){
        if(preorder.size()==0) return NULL;//第一步判空

        //第二步找到前序数组最后元素
        int rootg =preorder[0];
        TreeNode* root=new TreeNode(rootg);//该节点作为父亲节点

        if(preorder.size()==1) return root;//最后遍历如果前序数组为就一个,说明是叶子节点,直接返回

        //第三步分割数组
        //先找到分割位置
        int n;
        for(n=0;n<inorder.size();n++){
            if(inorder[n]==rootg) break;//记录分割位置
        }
        //通过分割位置分割中序数组
        vector<int> leftinorder(inorder.begin(),inorder.begin()+n);//中序左数组
        vector<int> rightinorder(inorder.begin()+n+1,inorder.end());//中序右数组

        //前序数组头部元素舍去
        preorder.erase(preorder.begin());

        //第四步分割前序数组
        vector<int> leftpreorder(preorder.begin(),preorder.begin()+leftinorder.size());//前序左数组
        vector<int> rightpreorder(preorder.begin()+leftinorder.size(),preorder.end());//前序右数组

        //第五步链接左右子节点
        root->left=traversal(leftinorder,leftpreorder);
        root->right=traversal(rightinorder,rightpreorder);

        return root;
    }
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {

        if (inorder.size() == 0 || preorder.size() == 0) return NULL;
        return traversal(inorder, preorder);

    }
};

112. 路径总和 - 力扣(LeetCode)

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

示例 1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

思路:从根节点开始依次搜索子节点,最后相加结果要等于总和,这里采用递归和回溯来判断是否接近于目标值。

解决:①首先,如果遇到叶子节点并且和为目标值,返回true;

                ②如果左右子节点都是叶节点但和不是目标值,返回false;

                ③判断左右子节点是否为空;

                ④先减去父节点的数再递归左右子节点;

                ⑤如果递归返回false,再加父节点数。

代码:

class Solution {
private:
    bool traversal(TreeNode* root,int cur){
        if(!root->left&&!root->right&&cur==0) return true;
        if(!root->left&&!root->right) return false;
        if(root->left){
            cur-=root->left->val;
            if(traversal(root->left,cur)) return true;
            cur+=root->left->val;//回溯父节点
        }
        if(root->right){
            cur-=root->right->val;
            if(traversal(root->right,cur)) return true;
            cur+=root->right->val;//回溯父节点
        }
        return false;
    }
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL) return false;
        return traversal(root, targetSum - root->val);
    }
};

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值