Day18 二叉树part05 513.找树左下角的值 112.路径总和 113.路径总和II 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树

Day18 二叉树part05 513.找树左下角的值 112.路径总和 113.路径总和II 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树

513. 找树左下角的值

方法一:迭代

class Solution {
public:
    int maxDepth = INT_MIN;
    int result;
    void traversal(TreeNode* node, int depth)
    {
        if(!node->left&&!node->right){
            if (depth > maxDepth) {
                maxDepth = depth;
                result = node->val;
            }
            return;
        }
        if(node->left) traversal(node->left,depth+1);
        if(node->right) traversal(node->right,depth+1);
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root, 0);
        return result;
    }
};

方法二:层序遍历

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue que;
        if(root!=nullptr) que.push(root);
        int result =0;
        while(!que.empty())
        {
            int size = que.size();
            for(int i=0; ival; //我们其实是每层第一个值不断覆盖,层序迭代到最后一层,就记录最后覆盖的值
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }
        return result;
    }
};

112. 路径总和

方法一:自娱自乐(递归)

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

方法二:卡尔法(递归)

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

方法三:极致的精简

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->right,targetSum-root->val) ||hasPathSum(root->left,targetSum-root->val);
    }
};

113. 路径总和 II

递归方法

class Solution {
public:
    vector> result;
    vector path;
    void traversal(TreeNode*node, int count)
    {
        if(!node->left&&!node->right)
        {
            if(count==0) result.push_back(path);  // 遇到了叶子节点且找到了和为sum的路径
            else return; // 遇到叶子节点而没有找到合适的边,直接返回
            return;
        }
        if(node->left){
            path.push_back(node->left->val);
            traversal(node->left,count-node->left->val);// 递归
            path.pop_back();  // 回溯
        }
        if(node->right){
            path.push_back(node->right->val);
            traversal(node->right,count-node->right->val);// 递归
            path.pop_back();// 回溯
        }
         return ;
    }
    vector> pathSum(TreeNode* root, int targetSum) {
        if (root == NULL) return result;
        path.push_back(root->val); // 把根节点放进路径
        traversal(root,targetSum-root->val);
        return result;
    }
};

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

思路

  • 第一步:如果数组大小为零的话,说明是空节点了。
  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。
  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点
  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)
  • 第五步:切割后序数组,切成后序左数组和后序右数组
  • 第六步:递归处理左区间和右区间
class Solution {
public:
    TreeNode* traversal (vector& inorder, vector& 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;
        }
        // 第四步:切割中序数组,得到 中序左数组和中序右数组

        // 左闭右开区间:[0, delimiterIndex)
        vector leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
        // [delimiterIndex + 1, end)
        vector rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end() );

        // 第五步:切割后序数组,得到 后序左数组和后序右数组

        // postorder 舍弃末尾元素,因为这个元素就是中间节点,已经用过了
        postorder.resize(postorder.size() - 1);

        // 左闭右开,注意这里使用了左中序数组大小作为切割点:[0, leftInorder.size)
        vector leftPostorder(postorder.begin(), postorder.begin() + leftInorder.size());
        // [leftInorder.size(), end)
        vector rightPostorder(postorder.begin() + leftInorder.size(), postorder.end());
        // 第六步: 递归处理左区间和右区间
        root->left = traversal(leftInorder, leftPostorder);
        root->right = traversal(rightInorder, rightPostorder);
        return root;
    }
    TreeNode* buildTree(vector& inorder, vector& postorder) {
        if (inorder.size() == 0 || postorder.size() == 0) return NULL;
        return traversal(inorder, postorder);
    }
};

105. 从前序与中序遍历序列构造二叉树

class Solution {
public:
        TreeNode* traversal (vector& preorder, vector& inorder){
        // 第一步
        if (preorder.size() == 0) return nullptr;
        // 第二步:前序遍历数组第一个元素,就是当前的中间节点
        int rootValue =preorder[0];
        TreeNode* root = new TreeNode(rootValue);
        // 叶子节点
        if (preorder.size() == 1) return root;
        // 第三步:找切割点
        int delimiterIndex;
        for (delimiterIndex = 0; delimiterIndex < inorder.size(); delimiterIndex++) {
            if (inorder[delimiterIndex] == rootValue) break;
        }
        // 第四步:切割中序数组,得到 中序左数组和中序右数组

        // 左闭右开区间:[0, delimiterIndex)
        vector leftInorder(inorder.begin(), inorder.begin() + delimiterIndex);
        // [delimiterIndex + 1, end)
        vector rightInorder(inorder.begin() + delimiterIndex + 1, inorder.end() );

        // 第五步:切割后序数组,得到 后序左数组和后序右数组

        // preorder 舍弃头部元素,因为这个元素就是中间节点,已经用过了
        preorder.erase(preorder.begin());

        // 左闭右开,注意这里使用了左中序数组大小作为切割点:[0, leftInorder.size)
        vector leftPreorder(preorder.begin(), preorder.begin() + leftInorder.size());
        // [leftInorder.size(), end)
        vector rightPreorder(preorder.begin() + leftInorder.size(), preorder.end());
        // 第六步: 递归处理左区间和右区间
        root->left = traversal(leftPreorder, leftInorder);
        root->right = traversal(rightPreorder, rightInorder);
        return root;
    }
    TreeNode* buildTree(vector& preorder, vector& inorder) {
        if (inorder.size() == 0 || preorder.size() == 0) return NULL;
        return traversal(preorder, inorder);
    }
};

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