路径总和,从中序与后序遍历序列构造二叉树

68 阅读2分钟

路径总和

[题目](112. 路径总和)

代码实现

/**
 * 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 traversal(TreeNode* cur, int count) {
        // 遇到叶子节点,并且计数为0
        if (!cur->left && !cur->right && count == 0) {
            return true;
        }
        // 遇到叶子节点直接返回
        if (!cur->left && !cur->right) {
            return false;
        }
        if (cur->left) {
            // 递归,处理节点
            count -= cur->left->val;
            if (traversal(cur->left, count)) {
                return true;
            }
            // 回溯,撤销处理结果
            count += cur->left->val;
        }
        if (cur->right) {
            count -= cur->right->val;
            if (traversal(cur->right, count)) {
                return true;
            }
            count += cur->right->val;
        }
        return false;
    }

    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL) {
            return false;
        }
        return traversal(root, sum - root->val);
    }
};

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

[题目](106. 从中序与后序遍历序列构造二叉树)

重点

确定节点的数值

  1. 后序数组为0,空节点
  2. 后序数组最后一个元素为节点元素
  3. 寻找中序数组位置作切割点
  4. 切中序数组
  5. 切后序数组
  6. 递归处理左右区间

代码实现

/**
 * 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) {
        // 后序数组为0,空节点
        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.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);
    }
};