Day 18 第六章 二叉树 part05

Day 18 第六章 二叉树 part05

5道题目
513. 找树左下角的值
112. 路径总和
113. 路径总和 II
105. 从前序与中序遍历序列构造二叉树
106. 从中序与后序遍历序列构造二叉树

解题理解

今天的题都挺难的,每道题只能说有一点思路,更别提实现了。

513

通过这题我明白了递归时什么时候需要对参数+1,其实+1就是回溯的过程,之前博客里的理解写的是不能确定该参数需不需要+1。

class Solution {
public:
    int res;
    int maxdepth = INT_MIN;
    void traversal(TreeNode* node, int depth){
        if(!node->left && !node->right){
            if(maxdepth < depth){
                maxdepth = depth;
                res = node->val;
            }
            
        }
        if(node->left){
            depth ++;
            traversal(node->left, depth);//traversal(node->left, depth + 1);
            depth --;
        }
        if(node->right){
            depth ++;
            traversal(node->right, depth);//traversal(node->right, depth + 1);
            depth --;
        }
    }
    int findBottomLeftValue(TreeNode* root) {
        if(root == nullptr) return 0;
        traversal(root, 1);
        return res;
    }
};

112和113

这两道题是同种题,也是通过这两题稍微理解了一点什么时候递归需要设置返回值。
112中,是将叶子节点的true一个一个返上去,而且传入的参数是目标值-当前值这个过程很巧妙
113中我一直在思考vector.clear放在那里,没想到不需要在递归里设置clear,而且这道题需要回溯的不止sum,还有记录路径的vector。

// 112. 路径总和
class Solution {
public:
    bool pathsum(TreeNode* node, int count){
        if(!node->left && !node->right && count == 0) return true;
        if(!node->left && !node->right) return false;
        if(node->left){
            count -= node->left->val;
            if(pathsum(node->left, count)) return true;
            count += node->left->val;
        }
        if(node->right){
            count -= node->right->val;
            if(pathsum(node->right, count)) return true;
            count += node->right->val;
        }
        return false;
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root == nullptr) return false;
        return pathsum(root, targetSum - root->val);
    }
};
//113. 路径总和 II
class Solution {
public:
    vector<vector<int>> res;
    vector<int> path;
    void traversal(TreeNode* node, int count){
        if(!node->left && !node->right && count == 0){
            res.push_back(path);
            return;
        }
        if(!node->left && !node->right) return;
        if(node->left){
            path.push_back(node->left->val);
            count -= node->left->val;
            traversal(node->left, count);
            count += node->left->val;
            path.pop_back();
        }
        if(node->right){
            path.push_back(node->right->val);
            count -= node->right->val;
            traversal(node->right, count);
            count += node->right->val;
            path.pop_back();
        }
        return;
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        if(root == nullptr) return res;
        path.push_back(root->val);
        traversal(root, targetSum - root->val);
        return res;
    }
};  

105和106

从两个遍历顺序确定一颗二叉树是个经典问题了,之前考研学数据结构有很深的印象,好像还记得不能从前序和后序遍历确定一颗二叉树,整体的流程我还记得,但是切割过程中,没想起来需要把已知(这两道题分别从前序和后序得到头节点,然后去前序与中序切割)的左(右)子树长度拿去前序或中序里切割。
然后106跟105的实现过程思想一致,但实现起来差别挺大,自己实现了一版实现过程完全一致的105,但时间和空间效率都很差。

//106. 从中序与后序遍历序列构造二叉树
class Solution {
public:
    TreeNode* traversal(vector<int>& inorder, vector<int>& postorder){
        if(postorder.size() == 0) return nullptr;
        TreeNode* root = new TreeNode(postorder[postorder.size() - 1]);
        if (postorder.size() == 1) return root;
        int index;
        for(index = 0; index < inorder.size(); index ++){
            if(inorder[index] == root->val) break;
        }
        vector<int> leftinorder(inorder.begin(), inorder.begin() + index);
        vector<int> rightinorder(inorder.begin() + index + 1, inorder.end());

        postorder.resize(postorder.size() - 1);

        vector<int> leftpostorder(postorder.begin(), postorder.begin() + leftinorder.size());
        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 nullptr;
        return traversal(inorder, postorder);
    }
};
//105. 从前序与中序遍历序列构造二叉树
class Solution {
public:
    TreeNode* traversal(vector<int>& preorder, vector<int>& inorder){
        if(inorder.size() == 0) return nullptr;
        TreeNode* root = new TreeNode(preorder[0]);
        if(inorder.size() == 1) return root;
        int index;
        for(index = 0; index < inorder.size(); index ++){
            if(inorder[index] == root->val) break;
        }
        vector<int> leftinorder(inorder.begin(), inorder.begin() + index);
        vector<int> rightinorder(inorder.begin() + index + 1, inorder.end());

        vector<int> newpreorder(preorder.begin() + 1, preorder.end());
        vector<int> leftpreorder(newpreorder.begin(), newpreorder.begin() + leftinorder.size());
        vector<int> rightpreorder(newpreorder.begin() + leftinorder.size(), newpreorder.end());
        root->left = traversal(leftpreorder, leftinorder);
        root->right = traversal(rightpreorder, rightinorder);
        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(preorder.size() == 0 || inorder.size() == 0) return nullptr;
        return traversal(preorder, inorder);
    }
};
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值