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

找树左下角的值

层序遍历

考虑遍历数的每一层,最下层的最左边元素就是树左下角的值。简单的层序遍历,在对每层遍历时都将第一个节点的值更新为返回值ans,最后返回ans。

class Solution {
public:
    queue<TreeNode*>queue;
    int findBottomLeftValue(TreeNode* root) {
        int ans;
        queue.push(root);
        while(!queue.empty()){
            int levelsize = queue.size();
            for(int i =0; i< levelsize;i++){
                TreeNode*cur = queue.front();
                if(i == 0){
                    ans = cur->val;//将ans更新为第一个节点的值
                }
                queue.pop();
                if(cur->left){
                    queue.push(cur->left);
                }
                if(cur->right){
                    queue.push(cur->right);
                }
            }
        }
        return ans;
    }
};

算法时间复杂度和空间复杂度均为O(n)。

递归法

可以考虑前序、中序和后序三种方式,因为这里只要求遍历到最深层,然后返回最深处第一个节点的值。

怎么找二叉树的左下角? 递归中又带回溯了,怎么办?| LeetCode:513.找二叉树左下角的值_哔哩哔哩_bilibiliicon-default.png?t=N7T8https://www.bilibili.com/video/BV1424y1Z7pn/?spm_id_from=333.788&vd_source=fc4a6e70e3a87b7ea67c2024e326e7c5

class Solution {
public:
    int max_depth = INT_MIN;//或者设为0,也可以
    int result;//返回的结果
    int depth = 0;//初始深度设定为0
    void travesal(TreeNode *root, int &depth){//注意这里传入的是depth的引用    
        if(root->left == nullptr and root->right == nullptr){//递归中找到根节点,若比最大深 //度大,则更新result(无论何种顺序,都是该深度下最左边的节点)                                 
            if(depth > max_depth){
                max_depth = depth;
                result = root->val;
            }
        }
        if(root->left){//注意这里的回溯,depth++后传入travesal,若到了根节点,则返回,depth--。
            depth++;
            travesal(root->left,depth);
            depth--;
        }
        if(root->right){//同上
            depth++;
            travesal(root->right,depth);
            depth--;
        }
    }
    int findBottomLeftValue(TreeNode* root) {
        travesal(root,depth);
        return result;      
    }
};

算法的时间复杂度和空间复杂度均为O(n)。

路径总和

递归法

我选择从根节点开始向下递归,并每次更新targetofsum的值,采取前序遍历的顺序,递归条件设定为若找到叶子节点等于更新后的targetsum,则返回true,否则递归完成后返回false。具体代码如下。

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        // 如果根节点为空,直接返回 false。
        if (root == nullptr) {
            return false;
        }
        // 如果根节点是叶子节点(即没有左右子节点),并且 targetSum 等于该节点的值,返回 true。
        if (root->left == nullptr && root->right == nullptr) {
            return targetSum == root->val;
        }
        // 更新 targetSum 为 targetSum - root->val。
        targetSum -= root->val;
        bool leftPath = hasPathSum(root->left, targetSum);
        bool rightPath = hasPathSum(root->right, targetSum);
        // 最后,如果左右子树中有任意一个存在满足条件的路径,返回 true;否则返回 false。
        return leftPath || rightPath;
    }
};

时间复杂度和空间复杂度均为O(n)。

路径总和ii

与路径总和i相类似的方式,不过每次递归都将一个temp数组递下去,并将节点的val值push_back到数组的尾部。

class Solution {
public:
    void findPaths(TreeNode* root, int targetSum, vector<int>& temp, vector<vector<int>>& ans) {
        if (root == nullptr) {
            return;
        }
        // 将当前节点的值添加到临时路径中
        temp.push_back(root->val);
        targetSum -= root->val;
        // 如果是叶子节点且路径和等于目标和,将路径添加到结果中
        if (root->left == nullptr && root->right == nullptr) {
            if (targetSum == 0) {
                ans.push_back(temp);
            }
        }
        // 递归处理左子树和右子树
        findPaths(root->left, targetSum, temp, ans);
        findPaths(root->right, targetSum, temp, ans);
        
        // 回溯:移除当前节点,以便继续探索其他路径
        temp.pop_back();
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<int> temp;
        vector<vector<int>> ans;
        findPaths(root, targetSum, temp, ans);
        return ans;
    }
};

从中序与后序遍历序列构建二叉树

递归法

需要把握后序遍历和中序遍历的特点,后序遍历的顺序是左右中,中序遍历的顺序是左中右,即后序遍历结果的最后一个位置为二叉树的根节点,再带入中序遍历中,中序遍历是左中右,即在我们已知根节点的情况下,可以在中序遍历中区分左子树和右子树。以leetcode上的实例举例,我们先在后序[9,15,7,20,3]和中序[9,3,15,20,7]这两个序列中,先从后序序列中找到树的根节点3,以节点3将中序分为左子树和右子树,之后再根据后序,找出左子树和右子树的根节点。依此顺序递归。由此可以写出以下代码。

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        //
        if(postorder.size() == 0){
            return nullptr;
        }
        int root_val = postorder[postorder.size()-1];
        TreeNode* root = new TreeNode(postorder[postorder.size()-1]);
        if(postorder.size() == 1)
            return root;
        //创建索引,找寻根节点在中序序列中的位置
        int index = -1;
        for(int i = 0 ; i < inorder.size(); i ++){
            if(inorder[i] == root_val){
                index = i;
                break;
            }
        }
        //根据索引区分中序的左右子树序列、后序的左右子树
        vector<int>inorederlefttree(inorder.begin(),inorder.begin() + index);
        vector<int>inorderrighttree(inorder.begin()+index+1,inorder.end());
        vector<int>postorderlefttree(postorder.begin(),postorder.begin()+inorederlefttree.size());
        vector<int>postorderrighttree(postorder.begin()+inorederlefttree.size(),postorder.end()-1);
        
        
        root -> left = buildTree(inorederlefttree,postorderlefttree);
        root -> right = buildTree(inorderrighttree,postorderrighttree);
        return root;
    }
};

算法的时间复杂度和空间复杂度为O(n)

从前序与中序遍历序列构建二叉树

        和前文类似,与之前的区别在于后序的最后一个节点为根节点,而前序的第一个节点为根节点,以此类推。

class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size() == 0)
            return nullptr;
        int root_val = preorder[0];
        TreeNode* root = new TreeNode(root_val);
        if(preorder.size() == 1)
            return root;
        int index = -1;
        for(int i = 0; i < inorder.size(); i++){
            if(inorder[i] == root_val){
                index = i;
                break;
            }
        }
        vector<int>inorderlefttree(inorder.begin(),inorder.begin()+index);
        vector<int>inorderrighttree(inorder.begin()+index+1,inorder.end());
        vector<int>preorderlefttree(preorder.begin()+1,preorder.begin()+1+inorderlefttree.size());
        vector<int>preorderrighttree(preorder.begin()+1+inorderlefttree.size(),preorder.end());

        root->left = buildTree(preorderlefttree,inorderlefttree);
        root->right = buildTree(preorderrighttree,inorderrighttree);
        return root;
    }
};

算法的时间复杂度和空间复杂度为O(n)。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值