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

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

513.找树左下角的值

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

思路:

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

核心代码:

cpp 复制代码
/**
 * 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即可。最后不要忘记回溯。

核心代码:

cpp 复制代码
/**
 * 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时把记录的路径加到答案数组就可以了。

核心代码:

cpp 复制代码
/**
 * 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.由左右子树的大小,我们再来分割后序序列,后序序列的前一部分和左子树序列长度相同的序列,就是左子树的后序遍历序列。后面一部分去掉最后一个点则是右子树的后序序列。

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

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

核心代码:

cpp 复制代码
/**
 * 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/

思路:

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

核心代码:

cpp 复制代码
/**
 * 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,题目不算难。

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

相关推荐
怀澈12223 分钟前
高性能服务器模型之Reactor(单线程版本)
linux·服务器·网络·c++
chnming19871 小时前
STL关联式容器之set
开发语言·c++
带多刺的玫瑰1 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
爱敲代码的憨仔1 小时前
《线性代数的本质》
线性代数·算法·决策树
威桑1 小时前
MinGW 与 MSVC 的区别与联系及相关特性分析
c++·mingw·msvc
熬夜学编程的小王1 小时前
【C++篇】深度解析 C++ List 容器:底层设计与实现揭秘
开发语言·数据结构·c++·stl·list
yigan_Eins1 小时前
【数论】莫比乌斯函数及其反演
c++·经验分享·算法
Mr.131 小时前
什么是 C++ 中的初始化列表?它的作用是什么?初始化列表和在构造函数体内赋值有什么区别?
开发语言·c++
阿史大杯茶1 小时前
AtCoder Beginner Contest 381(ABCDEF 题)视频讲解
数据结构·c++·算法
C++忠实粉丝1 小时前
计算机网络socket编程(3)_UDP网络编程实现简单聊天室
linux·网络·c++·网络协议·计算机网络·udp