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

文章涉及层序遍历的改进,路径总和的正确处理,以及如何通过中序和后序遍历来构造二叉树。重点在于理解递归方法和数据结构的运用。
摘要由CSDN通过智能技术生成

513.找树左下角的值

先复习了一遍层序遍历。

class Solution {
public:
    int bottomLeft=0; //最后一个结点的值
    int max_depth = INT_MIN;

    void traversal(TreeNode* cur, int depth){
        if (cur->left == nullptr && cur->right == nullptr){
            if (depth > max_depth){
                max_depth = depth;
                bottomLeft = cur->val;
                return ; //递归终止条件,找到最深度的叶子结点;由于左右都会遍历,最后停止递归时肯定是最是深度的那个。
            }
        }
        if (cur->left){
            depth++;
            traversal(cur->left, depth);
            depth--; //回溯
        }
        if (cur->right){
            depth++;
            traversal(cur->right, depth);
            depth--; //回溯
        }
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 0);

        return bottomLeft;
    }
};

犯的错误:将 int max_depth = INT_MIN;放在了traversal()中遍历;这会导致每次递归max_depth 都会被更新致使每次遍历都会更新结果bottomLeft。

112. 路径总和

class Solution {
public:
    bool traversal (TreeNode* cur, int count){
        if (!cur->left && !cur->right && count==0) return true; //判断该根-叶的路径上的值总和是否等于count
        if (!cur->left && !cur->right) return false;
        if (cur->left){
            count-=cur->left->val; //处理count的值先于判断count的值
            if (traversal(cur->left, count)) return true; //将true层层上传
            count+=cur->left->val; //回溯
        }
        if (cur->right){
            count-=cur->right->val;
            if (traversal(cur->right, count)) return true;
            count+=cur->right->val; //回溯
        }
        return false; //遍历完根结点的左右孩子,如果没有返回true则返回false
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (!root) return false;
        int count = targetSum;
        count-=root->val; //先处理count的值
        return traversal(root, targetSum - root->val);
    }
};

值得注意的点:
1、对count的处理顺序,先减去当前节点的值,之后判断其子节点是否能将count减完,之后回溯。
即这个过程

count-=cur->left->val; //处理count的值先于判断count的值
if (traversal(cur->left, count)) return true; //将true层层上传
count+=cur->left->val; //回溯

每次传入traversal需要继续被减的都是减去当前节点的值。

113.路径总和ii

class Solution {
public:
    vector<vector<int>> result;
    vector<int> path;
    void traversal(TreeNode* cur, int count){
        path.push_back(cur->val);
        if (cur->left==nullptr && cur->right==nullptr) {
            if (count==0) {//所有根-叶并且值总和等于给定值的路径,加入result
                result.push_back(path);
                return;
            }
            return;
        }
        if (cur->left){
            count -= cur->left->val;
            traversal(cur->left, count);
            path.pop_back();
            count += cur->left->val;
        }
        if (cur->right){
            count -= cur->right->val;
            traversal(cur->right, count);
            path.pop_back();//回溯1
            count += cur->right->val;//回溯2
        }
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        result.clear();
        path.clear();
        if (!root) return result;
        targetSum-=root->val;
        traversal(root, targetSum);
        return result;
    }
};

和卡哥写的略微不同,我的写法和之前那道求所有路径类似。 path.push_back(cur->val);放在遍历的最前面。其他的和上道题思路类似,先处理当前节点的值再计算还需要减去的部分。

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

通过后序找中间节点,用于切割中序数组。

class Solution {
public:
    TreeNode* traversal(vector<int>& inorder, vector<int>& postorder){
        if (postorder.size()==0) return nullptr;

        int rootValue = postorder[postorder.size()-1];
        TreeNode* root = new TreeNode(rootValue);

        if (postorder.size() == 1) return root;//如果后序遍历只有一个元素

        int delimiterIndex;
        for (delimiterIndex=0; delimiterIndex<inorder.size(); delimiterIndex++){
            if (inorder[delimiterIndex] == rootValue) break;
        }

        //[0, delimiterIndex)
        vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
        //[delimiterIndex, end)
        vector<int> rightInorder(inorder.begin() + delimiterIndex+1, inorder.end());

        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);
    }
};

注意:必须要有中序序列才能确定一棵二叉树,因为中序将二叉树的左右子树隔开。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值