算法训练1-day14-二叉树

30 阅读3分钟

今天是二叉树

  1. 513. 找树左下角的值

层序遍历

AC代码:

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        if (root == nullptr) return 0;
        queue<TreeNode*> nodes;
        nodes.push(root);
        int ans = 0;
        TreeNode* node = nullptr;
        while (!nodes.empty()) {
            int size = nodes.size();
            for (int i = 0; i < size; ++i) {
                node = nodes.front();
                nodes.pop();
                if (i == 0) ans = node->val;
                if (node->left != nullptr) nodes.push(node->left);
                if (node->right != nullptr) nodes.push(node->right);
            }
        }

        return ans;
    }
};
//递归
//左节点优先遍历,这样遇到的叶子一定是最左边的
//然后我们再看深度,如果深度更大,那就更新
class Solution {
public:
    int maxDepth = INT_MIN;
    int result;
    void traversal(TreeNode* root, int depth) {
        if (root->left == NULL && root->right == NULL) {
            if (depth > maxDepth) {
                maxDepth = depth;
                result = root->val;
            }
            return;
        }
        if (root->left) {
            traversal(root->left, depth + 1); // 隐藏着回溯
        }
        if (root->right) {
            traversal(root->right, depth + 1); // 隐藏着回溯
        }
        return;
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 0);
        return result;
    }
};
  1. 112. 路径总和

AC代码:

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

            return false;
        }

        return hasPathSum(root->left, targetSum - root->val) 
                || hasPathSum(root->right, targetSum - root->val);
    }
};
  1. 113. 路径总和 II

AC代码:

class Solution {
public:
    vector<vector<int>> ans;
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        if(root == nullptr) return ans;
        GetPath(root, targetSum, vector<int>());
        return ans;
    }

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

        if(root->left != nullptr) GetPath(root->left, targetSum - root->val, path);
        if(root->right != nullptr) GetPath(root->right, targetSum - root->val, path);
    }
};
  1. 106. 从中序与后序遍历序列构造二叉树

先从后序遍历中获取根节点的值,也就是postorder的最后一位,然后根据这个值找到它在inorder中的位置,再根据这个位置对inorder进行分割,左边就是左子树,右边就是右子树;然后因为前序遍历的长度必然等于对应的后序遍历的长度,因此接下来我们就可以根据分割后左右inorder子数组的长度对postorder数组进行分割;对于左右子树也是一样的操作,因此不断递归直到传递的数组长度为0

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

        int rootVal = postorder[m-1];
        TreeNode* root = new TreeNode(rootVal);
        
        // 获取rootVal在inorder中的位置
        int rootValPosInInorder = 0;
        while(inorder[rootValPosInInorder] != rootVal){
            rootValPosInInorder++;
        }

        // 按照rootVal将inorder分为两部分
        vector<int> leftInorder(inorder.begin(), inorder.begin()+rootValPosInInorder);
        vector<int> rightInorder(inorder.begin()+rootValPosInInorder+1, inorder.end());
        // 按照inorder分为的两部分的长度将postorder分为两部分
        vector<int> leftPostorder(postorder.begin(), postorder.begin()+rootValPosInInorder);
        vector<int> rightPostorder(postorder.begin()+rootValPosInInorder, postorder.end()-1);

        root->left = buildTree(leftInorder, leftPostorder);
        root->right = buildTree(rightInorder, rightPostorder);

        return root;
    }
};
  1. 105. 从前序与中序遍历序列构造二叉树
class Solution {
public:
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        return _buildTree(preorder, 0, preorder.size(), inorder, 0, inorder.size());
    }

    TreeNode* _buildTree(vector<int>& preorder, int preorderBegin, int preorderEnd,
                         vector<int>& inorder, int inorderBegin, int inorderEnd){
        
        if(preorderBegin == preorderEnd) return nullptr;
        
        int rootVal = preorder[preorderBegin];
        TreeNode* root = new TreeNode(rootVal);
        //注意我们从0开始,找到的是rootVal在完整的inorder中的下标
        //因此之后计算leftInorderEnd时不需要再加上leftInorderBegin
        //rootValIndexInInorder本身就是我们要的leftInorderEnd位置
        int rootValIndexInInorder = 0;
        while(inorder[rootValIndexInInorder] != rootVal){
            rootValIndexInInorder++;
        }

        // 左闭右开
        // 先序数组
        int leftInorderBegin = inorderBegin;
        int leftInorderEnd = rootValIndexInInorder;
        int rightInorderBegin = rootValIndexInInorder + 1;
        int rightInorderEnd = inorderEnd;

        // 后序数组
        int leftPreorderBegin = preorderBegin + 1;
        int leftPreorderEnd = leftPreorderBegin + (leftInorderEnd - leftInorderBegin);
        int rightPreorderBegin = leftPreorderEnd;
        int rightPreorderEnd = preorderEnd;

        // cout<<leftInorderBegin<<" "<<leftInorderEnd<<" "<<rightInorderBegin<<" "<<rightInorderEnd<<endl;
        // cout<<leftPreorderBegin<<" "<<leftPreorderEnd<<" "<<rightPreorderBegin<<" "<<rightPreorderEnd<<endl;
        root->left = _buildTree(preorder, leftPreorderBegin, leftPreorderEnd, 
                                inorder, leftInorderBegin, leftInorderEnd);
        root->right = _buildTree(preorder, rightPreorderBegin, rightPreorderEnd,
                                inorder, rightInorderBegin, rightInorderEnd);

        return root;
    }
};