代码随想录算法训练营29期Day18|LeetCode 513,112,113,106,105

  文档讲解:找树左下角的值  路径总和  从中序与后序遍历序列构造二叉树

513.找树左下角的值

题目链接:https://leetcode.cn/problems/find-bottom-left-tree-value/description/

思路:

        本题要求我们找到树最深一层的最左节点的值。搜索的话复杂度应该会高,判断条件也不好写。所以这题很明显使用迭代法进行层序遍历,每层记录最左节点(即第一个节点)的值即可。迭代完成后自然记录的是最深一层的最左节点值。

核心代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> q;
        int ans;
        if(root) q.push(root);
        while(!q.empty()){
            TreeNode* cur;
            int n=q.size();
            cur=q.front();
            ans=cur->val;
            while(n--){
                cur=q.front();
                q.pop();
                if(cur->left) q.push(cur->left);
                if(cur->right) q.push(cur->right);
            }
        }
        return ans;
    }
};

112.路径总和

题目链接:https://leetcode.cn/problems/path-sum/description/

思路:

        本题要求我们判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum

        那我们从根节点向下搜索即可,记录到当前节点的总和值,处理到叶子节点时,判断这个值是否等于targetSum即可,或者初始值设为-targetSum,每搜索到一个节点就把值加进去,到达叶子节点时判断总和是否为0即可。最后不要忘记回溯。

核心代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    bool dfs(TreeNode* cur,int sum){
        if(!cur->left&&!cur->right){
            if(sum==0) return true;
            else return false;
        }
        if(cur->left&&dfs(cur->left,sum+cur->left->val)) return true;
        if(cur->right&&dfs(cur->right,sum+cur->right->val)) return true;
        return false;
    }
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(!root) return false;
        return dfs(root,-1*targetSum+root->val);
    }
};

113.路径总和II

题目链接:https://leetcode.cn/problems/path-sum-ii/

思路:

       本题与上题进行深搜的方式和逻辑一模一样,唯一需要注意的地方是本题需要记录路径,开一个path记录即可,path可以是全局变量,也可以传参,最后判断路径的sum等于targetSum时把记录的路径加到答案数组就可以了。

核心代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    vector<vector<int>> ans;
    void dfs(TreeNode* cur,int sum,vector<int>& path){
        if(!cur->left&&!cur->right){
            if(!sum) ans.push_back(path);
            return;
        }
        if(cur->left){
            path.push_back(cur->left->val);
            dfs(cur->left,sum+cur->left->val,path);
            path.pop_back();
        }
        if(cur->right){
            path.push_back(cur->right->val);
            dfs(cur->right,sum+cur->right->val,path);
            path.pop_back();
        }
        return ;
    }
public:
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<int> path;
        if(root) path.push_back(root->val);
        if(root) dfs(root,root->val-targetSum,path);
        return ans;
    }
};

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

题目链接:https://leetcode.cn/problems/construct-binary-tree-from-inorder-and-postorder-traversal/description/

思路:

       首先我们要意识到一件事,中序为左中右,后序为左右中。下面我们分三步走:

       1.因此我们可以知道,后序遍历序列的最后一个点,就是根节点。

       2.查找根节点这个值在中序序列的位置,我们可以以此为分割得到左右两个序列。左边对应的是根节点左边子树的中序遍历序列,右边对应的是根节点右边子树的中序序列。知道左右子树的中序序列,我们也就知道了他们的大小。

       3.由左右子树的大小,我们再来分割后序序列,后序序列的前一部分和左子树序列长度相同的序列,就是左子树的后序遍历序列。后面一部分去掉最后一个点则是右子树的后序序列。

       到上面一步我们发现一件事情,我们得到了根节点,和左右子树分别的中序和后序序列。我们发现第一步就是根据中序后序来构造。因此我们对左右子树重复这三步即可。不断的迭代重复,直到子树剩下一个点,那就是叶子节点了,我们开始一步步回溯,把每个子树的根节点回溯到上一层,那就是上一层的左右子节点。

       回溯到最后,我们得到的就是根节点,并且树也建好了。

核心代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    TreeNode* travelsal(vector<int>& inorder,vector<int>& postorder){
        if(!postorder.size()) return NULL;
        int midval=postorder[postorder.size()-1];
        TreeNode* cur=new TreeNode(midval);
        if(postorder.size()==1) return cur;
        int mid;
        for(mid=0;mid<inorder.size();mid++)
          if(inorder[mid]==midval) break;
        vector<int> leftinorder(inorder.begin(),inorder.begin()+mid);
        vector<int> rightinorder(inorder.begin()+mid+1,inorder.end());
        postorder.pop_back();
        vector<int> leftpost(postorder.begin(),postorder.begin()+leftinorder.size());
        vector<int> rightpost(postorder.begin()+leftinorder.size(),postorder.end());
        cur->left=travelsal(leftinorder,leftpost);
        cur->right=travelsal(rightinorder,rightpost);
        return cur;
    }
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return travelsal(inorder,postorder);
    }
};

105.从前序与中序遍历序列构造二叉树

题目链接:https://leetcode.cn/problems/construct-binary-tree-from-preorder-and-inorder-traversal/

思路:

       会了上一道题就会这一道,本题与上题的处理方式和逻辑基本一致。唯一的区别是后序换成了前序,前序为中左右,因此我们的前序序列的第一个点为树的根节点,切割序列时注意这一点即可。

核心代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    TreeNode* travelsal(vector<int>& preorder,vector<int>& inorder){
        if(!preorder.size()) return NULL;
        int curval=preorder[0];
        TreeNode* cur=new TreeNode(curval);
        int curplace;
        for(curplace=0;curplace<inorder.size();curplace++)
          if(inorder[curplace]==curval) break;
        vector<int> leftin(inorder.begin(),inorder.begin()+curplace);
        vector<int> rightin(inorder.begin()+curplace+1,inorder.end());
        preorder.erase(preorder.begin());
        vector<int> leftpre(preorder.begin(),preorder.begin()+leftin.size());
        vector<int> rightpre(preorder.begin()+leftin.size(),preorder.end());
        cur->left=travelsal(leftpre,leftin);
        cur->right=travelsal(rightpre,rightin);
        return cur;
    }
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return travelsal(preorder,inorder);
    }
};

今日总结

        今日学习时长4h,题目不算难。

        剩下时间查论文看论文准备开题。

  • 28
    点赞
  • 39
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值