代码随想录 10.10 || 二叉树 LeetCode 513.找树左下角的值、112.路径总和、113.路径综合Ⅱ、106. 从中序与后序遍历序列构造二叉树

513.找树左下角的值

        给你一个二叉树的根节点 root,请找出该二叉树的 最底层 最左边 节点的值。题目要求找的是二叉树最底层、最左边的叶子节点的值,首先是最底层,其次是最左边。符合要求的节点也可能是在根节点的右子树,所以一直遍历左子树可能得不到正确答案。这里我们使用两种方法:一种是,利用前序(中序、后续都可,只要是左边优先)遍历,保持左边优先;一种是,层序遍历。

class Solution {
public:
    int maxDepth = INT_MIN;
    int result;

    void traversal(TreeNode* node, int depth) {
        if (node->left == nullptr && node->right == nullptr) {
            if (depth > maxDepth) {
                maxDepth = depth;
                result = node->val;
            }
            
            return ;
        }

        if (node->left != nullptr) traversal(node->left, depth + 1);
        if (node->right != nullptr) traversal(node->right, depth + 1);

        return ;
    }

    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 1);
        return result;
    }
};

        递归的三个步骤:1.确定形参列表,二叉树的根节点和用于跟踪递归层数的深度;2.确定终止条件,如果当前节点为叶子节点,且 depth 大于 maxDepth,则记录当前节点的内容,结束当前递归;3.确定基本递归逻辑,确保左边优先,所以先左再右。代码中为前序遍历,保证在每一层中,第一个遍历该层最左边的节点,如果该节点满足条件,修改 maxDepth 为 depth,同时 result 记录该节点的值,即使同一层存在其他节点,因为 depth 不大于 maxDepth,也不会修改 result 中的内容。

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        if (root != nullptr) que.push(root);
        int value = root->val;

        while (!que.empty()) {
            int size = que.size();

            while (size--) {
                TreeNode* node = que.front();
                que.pop();

                value = node->val;

                if (node->right != nullptr) que.push(node->right);
                if (node->left != nullptr) que.push(node->left); 
            }
        }
        return value;
    }
};

        上述代码为层序遍历实现求最左下角值,层序遍历很好理解,遍历至最底层,记录该层第一个遇到的节点,即为最底层、最左节点,只要确保左边优先即可,这是代码随想录里的思路。我在使用层序遍历时,略有不同。如代码所示,如果我们从右边开始遍历每一层,并逐层逐个记录元素的内容,最后记录的元素一定是最底层、最左的节点。因为遍历顺序是自右向左、自上向下,最后一个元素必定满足 最底层 最左边

112.路径总和

        给你二叉树的根节点 root 和一个表示目标和的整数 targetSum。判断该树中是否存在根节点到叶子节点的路径,这条路径上所有节点值相加等于目标和 targetSum。如果存在,返回 true;否则,返回 false。根据题意,必须是从根节点出发到叶子节点,这条路径上的值和等于目标和。如果存在一条满足题意的路径,返回真,反之假。我们先使用前序遍历(中序和后序也可,只需要遍历节点即可,不需要处理节点)的递归法解决问题。

        递归法三步骤,1.确定参数列表,二叉树的根节点,目标和;2.确定终止条件,如果当前节点为叶子节点,且路径上的节点和等于目标和,结束递归;3.确定递归基本逻辑,前序,根左右,一直向下即可。

class Solution {
public:
    bool traversal(TreeNode* node, int sum) {
        sum -= node->val;

        if (!node->left && !node->right && sum == 0) return true;

        if (node->left) {
            if (traversal(node->left, sum)) return true;
        }
            
        if (node->right) {
            if (traversal(node->right, sum)) return true;
        }

        return false;
    }

    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == nullptr) return false;
        return traversal(root, targetSum);
    }
};

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == nullptr) return false;
        if (!root->left && !root->right && targetSum == root->val) return true;

        return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
    }
};

        上述代码,定义了一个 bool 类型的递归函数 traversal,接受二叉树节点指针和一个整数作为变量,当 node 为叶子节点且路径和等于目标和时,结束递归,返回真。在向下递归的时候,如果找到一条符合要求的路径,直接结束递归函数,返回真。

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        stack<pair<TreeNode*, int>> st;
        if (root != nullptr) st.push(pair<TreeNode*, int>(root, root->val));

        while (!st.empty()) {
            pair<TreeNode*, int> node = st.top();
            st.pop();

            if (!node.first->left && !node.first->right && node.second == targetSum) return true;
            if (node.first->right) st.push(pair<TreeNode*, int>(node.first->right, node.second + node.first->right->val));
            if (node.first->left) st.push(pair<TreeNode*, int>(node.first->left, node.second + node.first->left->val));
        }
        return false;
    }
};

        第二种方法,迭代法,注意,和之前定义栈的类型不同,这里定义pair<TreeNode*,int>类型的栈,在 pair 中,第二个位置存放从根节点到当前节点的路径和,以 pair 中第二个元素和目标和是否相同作为判定依据。

113.路径总和Ⅱ

        在112.路径总和的基础上,返回所有满足条件的路径。

class Solution {
private:
    vector<vector<int>> result;
    vector<int> path;

    void traversal(TreeNode* node, int count) {
        count -= node->val;

        if (!node->left && !node->right && count == 0) {
            result.push_back(path);
            return ;
        }

        if (node->left) {
            path.push_back(node->left->val);
            traversal(node->left, count);
            path.pop_back();
        }

        if (node->right) {
            path.push_back(node->right->val);
            traversal(node->right, count);
            path.pop_back();
        }
        return ;
    }

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

};

        使用 path 记录走过的路径,result 为结果集。递归的终止条件与112.路径总和相同,当满足条件时,将 path 加入结果集 result。依旧是前序遍历,本题必须是前序遍历,因为需要在path中记录根节点的信息。注意在深入下一层时,向 path 中添加该节点元素,当返回上一层时,需要从path 中删除该节点元素,递归 + 回溯。

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

        

class Solution {
private:
    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;
        }

        vector<int> leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
        vector<int> rightInorder(inorder.begin() + delimiterIndex + 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;

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

        掌握的还不是很好,下次再聊。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值