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

本文介绍了如何在LeetCode中解决两个二叉树相关问题:找树左下角的值,以及通过中序和后序遍历来构造二叉树。提供了两种方法,分别是迭代和递归。同时讨论了路径总和问题及其解法。
摘要由CSDN通过智能技术生成

题目:513.找树左下角的值

文章链接:代码随想录

视频链接:LeetCode:513.找树左下角的值

题目链接:力扣题目链接

解法1:迭代遍历,一直取每层的第一个数,如果有新的一层则重新覆盖就是最底层的左节点

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        // 创建队列,存放二叉树指针
        queue<TreeNode* > que;
        // 判断根节点是否为空,不为空则放进元素
        if(root != NULL) que.push(root);
        // 返回结果
        int result = 0;
        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;
    }
};

解法2:递归

class Solution {
public:
    int MAX_Depth = INT32_MIN; // 最大深度
    int result;
    // 不需要返回值
    void traversal(TreeNode* node, int depth){  // depth 为当前的层数
         // 终止条件,碰到叶子节点
         if(node->left == NULL && node->right == NULL){
              if(depth > MAX_Depth){
                  MAX_Depth = depth;  // 更新最大深度
                  result = node->val;  // 更新结果
              }
            return ;
         }
         // 因为在叶子节点就终止,所以需要判断左右孩子是否为空
         // 处理的逻辑也跟遍历差不多,如果同层会优先遍历左子数,
         // 这时候已经给MAX_Depth更新层数了,如果没有更深层时,就不会再对结果更新。
         if(node->left != NULL){
             depth++;  //  0->1   
             traversal(node->left,depth); // [1]
             depth--;  // 回溯
         }
        if(node->right != NULL){
             depth++;
             traversal(node->right,depth);
             depth--;  // 回溯
         }
         return;
    }

    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 0);
        return result;
    }
};

题目:112. 路径总和 、113.路径总和ii

 文章链接:代码随想录

视频链接:LeetCode:112. 路径总和 、113.路径总和ii

题目链接:力扣题目链接   力扣题目链接2

解法1:

class Solution {
public:
    bool reversal(TreeNode* node, int count){
        // 遍历的叶子节点就终止
        if(node->left == NULL && node->right == NULL){
            // 用相减的方式判断是否达到目标值
            if(count == 0) return true;
            else{
                return false;
            }
        }
        // 左,在叶子节点终止,照例判断是否为空
        if(node->left != NULL){
            count -= node->left->val; // 因为当进入下一层递归的时候直接判断count是否为空了,所以要在递归上层对值进行处理
            if(reversal(node->left,count)) return true;  // 如果返回true 则说明找到了,向上进行返回
            count += node->left->val;  // 回溯,再把值加回来
            // 精简到一起, 传入的是count-node->left->val,count值并没有改变,遍历另一条路径的时候相减又是其他的值
            // if(reversal(node->left,count-node->left->val)) return true; 
        }
        if(node->right != NULL){
            count -= node->right->val; 
            if(reversal(node->right,count)) return true;  
            count += node->right->val;  // 回溯      
        }
        return false;
    }

    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL) return false;
        return reversal(root, targetSum-root->val);
    }
};

解法2:

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void reversal(TreeNode*node, int count){
        if(!node->left && !node->right && count==0) {
            result.push_back(path);  // 把路径放到结果数组里
            return;
        }
        if (!node->left && !node->right) return ; // 遇到叶子节点而没有找到合适的边,直接返回
        // 左
        if(node->left){
            // 把数组放入路径中
            path.push_back(node->left->val);
            count -= node->left->val;
            reversal(node->left, count); // 递归
            count += node->left->val;    // 回溯
            path.pop_back();             // 回溯
        }
        if(node->right){
            // 把数组放入路径中
            path.push_back(node->right->val);
            count -= node->right->val;
            reversal(node->right, count); // 递归
            count += node->right->val;    // 回溯
            path.pop_back();             // 回溯
        }
        return;
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
         result.clear(); // 保证结果数组里为空的
         path.clear();
         if(root == NULL) return result;
         path.push_back(root->val);  // 把根节点放入,常忘记
         reversal(root, targetSum-root->val); // 目标值减去根节点的值
         return result;
    }
};

题目:106.从中序与后序遍历序列构造二叉树、105.从前序与中序遍历序列构造二叉树

 文章链接:代码随想录

视频链接:LeetCode:106.从中序与后序遍历序列构造二叉树口

题目链接:力扣题目链接  力扣题目链接

解法1:

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

class Solution {
public:
    TreeNode* traversal(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 delimiterInder;  // delimiterInder==1
        for(delimiterInder=0; delimiterInder<inorder.size(); delimiterInder++){
            if(inorder[delimiterInder] == rootValue) break; // 退出循环
        }
        // 第四步:切割中序数组,得到 中序左数组和中序右数组
        // 左闭右开区间:[0,delimiterInder) [0,1)
        vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterInder); // [9]
        vector<int> rightInorder(inorder.begin()+delimiterInder+1, inorder.end()); // +1 第delimiterInder个元素不要
        // 第五步:切割后序数组,得到 后序左数组和后序右数组
        // 先去除掉最后一个元素
        postorder.resize(postorder.size()-1); // 进行一个缩减
        // 左闭右开,注意这里使用了左中序数组大小作为切割点:[0, leftInorder.size)
        vector<int> leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
        // [leftInorder.size(), end)
        vector<int> rightPostorder(postorder.begin() + leftInorder.size(), postorder.end()); 

        // 第六步 
        root->left = traversal(leftInorder,leftPostorder);
        root->right = traversal(rightInorder,rightPostorder);
        return root; 
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if (inorder.size() == 0 || postorder.size() == 0) return NULL;
        return traversal(inorder, postorder);
    }
};

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

class Solution {
public:
    TreeNode* traversal(vector<int>& preorder, vector<int>& inorder){
        // 第一步 如果后序数组为空,则说明到叶子节点了
        if(preorder.size() == 0) return NULL;
        // 第二步,遍历前序数组的第一个元素作为分割点
        int rootValue = preorder[0];
        TreeNode* root = new TreeNode(rootValue); //创建二叉树节点
        // 叶子节点, 分割后可能没有元素,可能只剩一个,也可能剩很多
        if(preorder.size() == 1) return root;
        // 第三步,找分割点
        int delimiterInder;  // delimiterInder==1
        for(delimiterInder=0; delimiterInder<inorder.size(); delimiterInder++){
            if(inorder[delimiterInder] == rootValue) break; // 退出循环
        }
        // 第四步:切割中序数组,得到 中序左数组和中序右数组
        // 左闭右开区间:[0,delimiterInder) [0,1)
        vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterInder); // [9]
        vector<int> rightInorder(inorder.begin()+delimiterInder+1, inorder.end()); // +1 第delimiterInder个元素不要

        // 第五步:切割前序数组,得到 前序左数组和前序右数组

        // 左闭右开,注意这里使用了左中序数组大小作为切割点:[1, leftInorder.size+1)  不要第一个元素
        vector<int> leftPreorder(preorder.begin()+1, preorder.begin() + 1 + leftInorder.size());
        // [leftInorder.size()+1, end)
        vector<int> rightPreorder(preorder.begin() + 1 + leftInorder.size(), preorder.end());

        // 第六步 
        root->left = traversal(leftPreorder,leftInorder);
        root->right = traversal(rightPreorder,rightInorder);
        return root; 
    }

    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if (inorder.size() == 0 || preorder.size() == 0) return NULL;
        return traversal(preorder,inorder);
    }
};
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值