2022年10月31日算法学习打卡

83 阅读3分钟

day 18 第六章 二叉树

今日内容

  • 513.找树左下角的值

    1. 路径总和 113.路径总和ii
  • 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构造二叉树

详细布置

找树左下角的值

本地递归偏难,反而迭代简单属于模板题, 两种方法掌握一下

题目链接/文章讲解/视频讲解:programmercarl.com/0513.%E6%89…

思路:

迭代法特别的简单,只要层次遍历整个二叉树,每次记录该层中最左边的元素即可。

递归法主要是确定某次遍历中。是否为最后一层,就需要用一个maxDeepth用于记录当前遍历的层数。

代码:

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

迭代法

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)
        {
            depth++;
            traversal(root->right,depth);
            depth--;
        }

        return;

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

    }
};

路径总和

本题 又一次设计要回溯的过程,而且回溯的过程隐藏的还挺深,建议先看视频来理解

\112. 路径总和,和 113. 路径总和ii 一起做了。 优先掌握递归法。

题目链接/文章讲解/视频讲解:programmercarl.com/0112.%E8%B7…

思路: 递归遍历整个二叉树,记录当前路径各个节点的总和,注意回退时需要减掉当前节点的值,而在这里面回退有多种条件。

代码:

class Solution {
public:
    int sum = 0;
    int flag = 0;
    void preTravser(TreeNode* root,int t){
        if(!root) return;
        sum += root->val;
        if(!root->left&&!root->right){
            if(sum == t)
            {
                flag=1;
            }
            sum-=root->val;
            return;
        }
        if(root->left)   preTravser(root->left,t);
        if(root->right)  preTravser(root->right,t);
        sum-=root->val;
        return;
    }

    bool hasPathSum(TreeNode* root, int targetSum) {
        preTravser(root,targetSum);
        return flag;
    }
};

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

本题算是比较难的二叉树题目了,大家先看视频来理解。

106.从中序与后序遍历序列构造二叉树,105.从前序与中序遍历序列构造二叉树 一起做,思路一样的

题目链接/文章讲解/视频讲解:programmercarl.com/0106.%E4%BB…

思路: 左右递归切割字符串,注意区间左闭右开,以及抛弃的元素。

class Solution {
private:
    TreeNode* traversal(vector<int>& inorder, vector<int>& postorder) {
        if(!postorder.size()) 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;
        }

        //切割中序数组 左闭右开
        vector<int> leftInorder(inorder.begin(),inorder.begin()+delimiterIndex);
        vector<int> rightInorder(inorder.begin()+delimiterIndex+1,inorder.end());

        // postorder 舍弃末尾元素
        postorder.resize(postorder.size() - 1);

        //切割后序数组 左闭右开 注意与中序切割的思路不同 不需要+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 NULL;
        return traversal(inorder, postorder);
    }
};