代码随想录第二十天 | 513. 找树左下角的值,路径总和,106. 从中序与后序遍历序列构造二叉树

513. 找树左下角的值 

第一想法:感觉用层序遍历比用递归遍历容易很多,层序遍历好久没写了,先试试。只会写遍历模板,其余的不太会写了...

看完想法:层序遍历还是复习一下。在que.push(root)前,先验证一下root是否为空。并用一个vector<vector<int>> vec 和 vector<int> tmp分别存储层序遍历后的二叉树和每层的二叉树。按照模板更改的话,只需要记录每行的第一个元素就可以了,到最后就会覆盖成最后一行的第一个的。在往深层遍历时,应该选用记录front的变量去递归,而不是root

递归想法:建立两个全局变量,一个存储最大深度,一个存储最大深度的最大值,然后使用回溯

//层序遍历法
int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        if(root != nullptr) que.push(root);
        int result = 0;
        while(!que.empty()){
            int size = que.size();//每层的大小是不一样的
            
            for(int i = 0; i< size; i++){
                TreeNode* tmp = que.front();
                que.pop();
                if(i == 0 ) result =  tmp->val;
                if(tmp->left) que.push(tmp->left);
                if(tmp->right) que.push(tmp->right);
            }
        }
        return result;

    }
class Solution {
public:
    int maxDepth = INT_MIN;
    int result;
    void traversal(TreeNode* root, int depth) {
        if (root->left == NULL && root->right == NULL) {
            if (depth > maxDepth) {
                maxDepth = depth;
                result = root->val;
            }
            return;
        }
        if (root->left) {
            depth++;
            traversal(root->left, depth);
            depth--; // 回溯
        }
        if (root->right) {
            depth++;
            traversal(root->right, depth);
            depth--; // 回溯
        }
        return;
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 0);
        return result;
    }
};

路径总和

第一想法:使用回溯,设置两个全局变量,用来存储bool和每次路径上的总和,但是好像有一种情况报错了

看完想法:注意,设置的全局变量不能成为局部函数的形参,这样会有歧义!正确做法是,当作一个变量就行;在回溯时,加入的应该是下一个即将要遍历的元素,即root->left->val而不是当前的元素值。

if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
if (!cur->left && !cur->right) return false; // 遇到叶子节点直接返回

 在回溯中,遇到合适的路径要及时返回,如这里就是if(traversal) return true;

在路径搜索Ⅱ中,由于不需要对返回值作处理,所以递归函数的返回值是void

vector<vector<int>> result;
    vector<int> path;
    void traversal(TreeNode* root, int count){
        if(!root->left && !root->right && count==0){
            result.push_back(path);
        }
        if(!root->left && !root->right) return ;
        
        
        if(root->left){
            count-=root->left->val;
            path.push_back(root->left->val);
            traversal(root->left, count);
            count+=root->left->val;
            path.pop_back();
        }
        if(root->right){
            count-=root->right->val;
            path.push_back(root->right->val);
            traversal(root->right, count);
            count+=root->right->val;
            path.pop_back();
        }
    }


    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        if(root==nullptr) return result;
        path.push_back(root->val);
        traversal(root, targetSum-root->val);
        return result;

    }

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

第一想法:切割中序数组使用后序的最后一个元素,不难。重点是如何切割后序数组,但不会...

看完想法:关键是,中序数组的大小和后续数组是相同的因此可以以左中序数组大小来切割。剩下的就是正常递归勒。在递归的时候,使用root->left, right接收,因为递归函数从后序数组的左右子列中取元素作为节点

这道题目使用for循环遍历来获取后序节点的下标,不好用find(),因为需要有<algorithem>头文件

定义vector的时候,利用begin(), end(), 等指针,直接使用括号

    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;
        //取postorder最后一个加入树中

        int value_index=0;
        for(; value_index<inorder.size(); value_index++){
            if(inorder[value_index]==rootValue) break;
        }
        //在C++中,这种fuction(a:b)的形式是左闭右开,即[a, b)]
        vector<int> left_inorder(inorder.begin(), inorder.begin()+value_index);
        vector<int> right_inorder(inorder.begin()+value_index+1, inorder.end());

        //删除后序最后一个
        postorder.resize(postorder.size()-1);
        //处理后序
        vector<int> left_postorder(postorder.begin(), postorder.begin()+left_inorder.size());
        vector<int> right_postorder(postorder.begin()+left_inorder.size(), postorder.end());
        //递归逻辑
        root->left = traversal(left_inorder, left_postorder);
        root->right = traversal(right_inorder, right_postorder);
        return root;

    }

    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        //如果为大小为1,直接返回Null就行
        if(inorder.size()==0) return nullptr;
        return traversal(inorder, postorder);
    }

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

第一想法:如果使用erase删除vector元素值的话,erase的输入为指针,指向要删除元素的值

TreeNode* traversal(vector<int>& preorder, vector<int>& inorder){
        //终止条件,如果preoder为0,返回
        if(preorder.size()==0) return nullptr;
        int rootvalue = preorder[0];
        TreeNode* root = new TreeNode(rootvalue);
        //叶子节点
        if(preorder.size()==1) return root;
        int value_index = 0;
        for(; value_index<inorder.size(); value_index++){
            if(inorder[value_index]==rootvalue) break;
        }

        //切割
        vector<int> left_inorder(inorder.begin(), inorder.begin() + value_index);
        vector<int> right_inorder(inorder.begin() +value_index+1, inorder.end());
        preorder.erase(preorder.begin());

        vector<int> left_preorder(preorder.begin(), preorder.begin() + left_inorder.size());
        vector<int> right_preorder(preorder.begin()+ left_inorder.size(), preorder.end() );

        root->left = traversal(left_preorder, left_inorder);
        root->right = traversal(right_preorder, right_inorder);
        return root;

    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return traversal(preorder, inorder);

    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值