day 18二叉树(五)

day18
代码随想录
2023.12.16

1. 513找树左下角的值
这道题很直观的就是想到层序遍历,最后一层的第一个节点值就是我们需要的,而且很偷懒的是,不用判断是不是最后一层,每一层第一个节点值都保存,会覆盖,最后的值就是我们要的。
最后看代码随想录还讲了递归写法,就是在递归时加了个深度变量,最深且是左节点的就是我们要找的值,挺麻烦的,不细说了

/**
 * 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:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        if(root!=NULL) que.push(root);
        int result;
        while(!que.empty()){
            int size = que.size();
            for(int i=0;i<size;i++){
                TreeNode*node = que.front();
                que.pop();
                if(i==0) result = node->val;
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }
        return result;
    }
};

2. 112路经总和
这道题跟前几天做的一道所有路径很相似,那道题是将所有路径要要求打印出来,这是求和,思路是一样的,只是在最终路径处理上不同,这道题在叶子节点是将path的值全部相加,如果==targetsum,则返回true即可。

/**
 * 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 hasPathSum(TreeNode* root, int targetSum) {
        vector<int> path;
        if(root==NULL) return false;
        return travel(root, path, targetSum);
    }
    bool travel(TreeNode*node, vector<int>& path, const int target){
        path.push_back(node->val);
        bool lefti=false;
        bool righti=false;
        if(node->left){
            lefti=travel(node->left, path, target);
            path.pop_back();
        }
        if(node->right){
            righti=travel(node->right, path, target);
            path.pop_back();
        }
        if(node->left==NULL && node->right==NULL){
            int sum=0;
            for(int i=0;i<path.size();i++){
                sum +=path[i];
            }
            cout<<sum<<endl;
            if(sum==target) return true;
        }
        return (lefti||righti);
        
        
    }
};

3. 106从中序和后续遍历结果构造二叉树
这道题是这道时间遇到的最难一题了。拿到后有些没有头绪,手写结果很简单,没什么那难度,但代码实现就不知道怎么写了,看了代码随想录文字讲解,悟了一点;
首先明确,是要递归处理的,每次传入两个数组,构造子树。重点是就是函数的实现。每次递归都是以后序遍历的最后一个元素为重点的,该元素就是本次递归的根节点,以该节点为中心,将中序遍历划分为两个部分,就是下次递归的左右子树的中序遍历结果。所以中序遍历很好切割,思路就是,根据后序遍历找到中心点,再在中序遍历找到中心点的位置,以该位置分割中序遍历数组;那么,后续遍历怎么分割?后续遍历没有中序遍历那么明显的分割点,但要知道,中序遍历和后序遍历的数组大小是相等的,所以知道中序遍历分割结果,可以根据该结果去按大小分割后续遍历,但要注意顺序。最终得到两个中序遍历,两个后序遍历,在分别匹配传给递归函数构造本次递归函数的根节点的左右子树。即可

/**
 * 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* traversal (vector<int>& inorder, vector<int>& postorder) {
        if (postorder.size() == 0) return NULL;

        // 后序遍历数组最后一个元素,就是当前的中间节点
        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 + 1, end)
        vector<int> rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end() );

        // postorder 舍弃末尾元素
        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);
    }
};

你可能感兴趣的:(LeetCode刷题记录,算法,数据结构,c++,leetcode)