随想录二刷Day19——二叉树

文章目录

  • 二叉树
    • 16. 找树左下角的值
    • 17. 路径总和
    • 18. 从中序与后序遍历序列构造二叉树

二叉树

16. 找树左下角的值

513. 找树左下角的值

思路1:
先序遍历二叉树,每到达一个更深的层,更新第一次遇到的节点。

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        preorder(root, 0);
        return ans;
    }

private:
    int ans, depth = -1;
    void preorder(TreeNode *root, int depth) {
        if (root == NULL) return ;
        if (this->depth < depth) {
            this->depth = depth;
            ans = root->val;
        }
        preorder(root->left, depth + 1);
        preorder(root->right, depth + 1);
    }
};

思路2:
层序遍历,每到一个新的层将第一个节点的值更新为答案。

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        preorder(root, 0);
        return ans;
    }

private:
    int ans, depth = -1;
    void preorder(TreeNode *root, int depth) {
        if (root == NULL) return ;
        if (this->depth < depth) {
            this->depth = depth;
            ans = root->val;
        }
        preorder(root->left, depth + 1);
        preorder(root->right, depth + 1);
    }
};

17. 路径总和

112. 路径总和

思路1: 递归
在每个叶子节点处查看当前路径的总和。

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        return preorder(root, 0, targetSum);
    }

private:
    bool preorder(TreeNode *root, int sum, int targetSum) {
        if (root == NULL) return false;
        if (!root->left && !root->right) { // 遇到叶子节点
            if (sum + root->val == targetSum) return true;
            else return false;
        }
        return preorder(root->left, sum + root->val, targetSum) 
            || preorder(root->right, sum + root->val, targetSum);
    }
};

思路2: 迭代法
思路同上

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL) return false;
        stack<pair<TreeNode *, int>> stk;
        stk.push({root, root->val});

        while (!stk.empty()) {
            pair<TreeNode *, int> node = stk.top(); stk.pop();
            if (!node.first->left && !node.first->right) { // 叶子节点
                if (node.second == targetSum) return true;
            }
            if (node.first->left) stk.push({node.first->left, node.second + node.first->left->val});
            if (node.first->right) stk.push({node.first->right, node.second + node.first->right->val});
        }
        return false;
    }
};

附加一题:
113. 路径总和 II

思路:
到记录每条路径上的节点值,遇到叶子节点,如果路径值之和等于目标值,则将该路径加入结果。

class Solution {
public:
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<vector<int>> result;
        if (root == NULL) return result;
        vector<int> path;
        path.push_back(root->val);
        preorder(root, targetSum - root->val, result, path);
        return result;
    }

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

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

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

思路:
后续遍历的最后一个元素是根节点(之后为每棵子树的根节点)
利用该节点将中序遍历结果划分为左右子树的中序遍历结果
根据该节点的左子树的中序遍历结果可以得到左子树的节点个数,就可以将后续遍历结果划分为左右子树
再对左右子树递归上面的过程。

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

private:
    TreeNode *buildTree(vector<int> &inorder, vector<int> &postorder, int Ibegin, int Iend, int Pbegin, int Pend) {
        if (Ibegin == Iend) return NULL;
        TreeNode *root = new TreeNode(postorder[Pend - 1]);
        
        if (Pend - Pbegin == 1) return root;

        int diveIndex;
        for (diveIndex = Ibegin; diveIndex < Iend; diveIndex++) {
            if (inorder[diveIndex] == root->val) break;
        }
        // 切割中序数组
        // 左中序数组,左闭右开
        int leftIbegin = Ibegin;
        int leftIend = diveIndex;
        // 右中序数组,左闭右开
        int rightIbegin = diveIndex + 1;
        int rightIend = Iend;

        // 切割后续数组
        // 左后续数组
        int leftPbegin = Pbegin;
        int leftPend = leftPbegin + diveIndex - Ibegin;
        // 右后续数组
        int rightPbegin = leftPend;
        int rightPend = Pend - 1;

        root->left = buildTree(inorder, postorder, leftIbegin, leftIend, leftPbegin, leftPend);
        root->right = buildTree(inorder, postorder, rightIbegin, rightIend, rightPbegin, rightPend);

        return root;
    }
};

你可能感兴趣的:(代码随想录,leetcode,算法,数据结构)