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

目录

一、513. 找树左下角的值

二、112. 路径总和

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


一、513. 找树左下角的值

题目链接:力扣

文章讲解:代码随想录

视频讲解: 怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode:513.找二叉树左下角的值

题目:

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

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

代码:

/**
 * 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:/*
    void dfs(TreeNode* root, int depth, int& max_depth, int& ans){
        if(!root) return;
        if (!root->left && !root->right){
            if(depth > max_depth){
                max_depth = depth;
                ans = root->val;
            }
        }
        dfs(root->left, depth+1, max_depth, ans);
        dfs(root->right, depth+1, max_depth, ans);
        return;

    }
    int findBottomLeftValue(TreeNode* root) {
        int depth = 0;
        int max_depth = -1;
        int ans = 0; 
        dfs(root, depth, max_depth, ans);
        return ans;
    }*///迭代
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        que.push(root);
        int ans = 0;
        while(!que.empty()){
            TreeNode* node = que.front();
            que.pop();
            if (node->right) que.push(node->right);
            if (node->left) que.push(node->left);
            ans = node->val;
        }
        return ans;
    }
};

时间复杂度: O(n)                                        空间复杂度: O(n)

⏲:8:14

总结:先序遍历,在同一层中,先左后右。在迭代中,使用队列,先进先出,将左子树后入,可使最后留下的即为所求的。

二、112. 路径总和

题目链接:力扣

文章讲解:代码随想录

视频讲解:拿不准的遍历顺序,搞不清的回溯过程,我太难了! | LeetCode:112. 路径总和

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

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

代码:

/**
 * 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:
    //递归正序
    /*bool order(TreeNode* node, int sum, int targetSum)
    {
        if (!node->left && !node->right)
        {
            if (sum == targetSum) return true;
            else 
                return false;
        }
        bool leftbool = false, rightbool = false;
        if (node->left) leftbool = order(node->left, sum + node->left->val, targetSum);
        if (node->right) rightbool = order(node->right, sum + node->right->val, targetSum);
        return leftbool || rightbool;
        
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (!root) return false;
        return order(root, root->val, targetSum);
    }*/
    //递归倒减
    /*bool order(TreeNode* node, int sum)
    {
        if (!node) return false;
        if (!node->left && !node->right && sum == node->val) return true;
        return order(node->left, sum - node->val) || order(node->right, sum - node->val);
        
    }*/
    bool hasPathSum(TreeNode* root, int targetSum) {
        //return order(root, targetSum);
        //迭代法,前序遍历
        stack<pair<TreeNode*, int>> st;
        if (!root) return false;
        st.push(pair<TreeNode*, int>(root, root->val));
        while (!st.empty())
        {
            pair<TreeNode*, int> node = st.top();
            st.pop();
            if (!node.first->left && !node.first->right && node.second == targetSum) return true;
            if (node.first->left) 
                st.push(pair<TreeNode*, int>(node.first->left, node.second + node.first->left->val));
            if (node.first->right)
                st.push(pair<TreeNode*, int>(node.first->right, node.second + node.first->right->val));
        }
        return false;
    }
};

113. 路径总和 II

/**
 * 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 traversal(TreeNode* node, int sum, vector<int> &path) 
    {
        if (!node->left && !node->right) 
        {
            if (sum == 0)
                ans.emplace_back(path);
            return;
        }

        if (node->left) 
        {
            path.emplace_back(node->left->val);
            traversal(node->left, sum - node->left->val, path);
            path.pop_back();
        }
        if (node->right) 
        {
            path.emplace_back(node->right->val);
            traversal(node->right, sum - node->right->val, path);
            path.pop_back(); 
        }
        return;
    }
public:
    vector<vector<int>> pathSum(TreeNode* root, int targetsum) {
        if (!root) return ans;
        vector<int> path;
        path.push_back(root->val);
        traversal(root, targetsum - root->val, path);
        return ans;
    }
};

时间复杂度: O(n)                                        空间复杂度: O(n)

⏲:11:04

总结:1.路径要返回值,可提前结束遍历,全搜索不用返回值,储存在全局变量或传地址数组中。2.路径问题,关键在于判断递归结束条件,其他按正常递归写。3.回溯:本层依旧使用就回溯,不用就不需要。

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

题目链接:力扣

文章讲解:代码随想录

视频讲解:坑很多!来看看你掉过几次坑 | LeetCode:106.从中序与后序遍历序列构造二叉树

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

代码:

/**
 * 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:
    TreeNode* creat_tree(vector<int>& inorder, int inorder_begin, int inorder_end, vector<int>& postorder, int postorder_begin, int postorder_end) {
        if (postorder_begin > postorder_end) return NULL;
        int root_value = postorder[postorder_end];
        TreeNode* root = new TreeNode(root_value);
        if (postorder_end == postorder_begin) return root;
        int target = 0;
        for(target = inorder_begin; target <= inorder_end; target++)
            if (inorder[target] == root_value) break; 
        root->left = creat_tree(inorder, inorder_begin, target-1, postorder, postorder_begin, postorder_begin+target-inorder_begin-1);
        root->right = creat_tree(inorder, target+1, inorder_end, postorder, postorder_begin+target-inorder_begin, postorder_end-1);
        return root;
    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        return creat_tree(inorder, 0, inorder.size()-1, postorder, 0, postorder.size()-1);
    }
};

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

/**
 * 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:
    TreeNode* order(vector<int> &inorder, int inlt, int inrt, vector<int> &postorder, int pslt, int psrt)
    {
        if (inlt > inrt) return NULL;
        TreeNode* node = new TreeNode(postorder[pslt]);
        if (inrt-inlt == 0) return node;
        int  x = 0;
        for (int i = inlt; i <= inrt; i++)
            if (inorder[i] == postorder[pslt])
            {
                x = i;
                break;
            }
        node->left = order(inorder, inlt, x-1, postorder, pslt+1, x-inlt+pslt);
        node->right = order(inorder, x+1, inrt, postorder, x-inlt+pslt+1, psrt);
        return node;

    }
    TreeNode* buildTree(vector<int>& postorder, vector<int>& inorder) {
        return order(inorder, 0, inorder.size()-1, postorder, 0, postorder.size()-1);
    }
};

总结:1.构造是通过不同序列的切割逐渐组成的,切割过程中使用索引更加方便且减少时间复杂度。2.切割过程注意循环不变量(习惯左闭右闭)。3.若只有先序和后序不能作出中序,没有中序遍历无法确定左右部分,无法分割。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值