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

513.找树左下角的值

递归法:

因为本题没有中间结点的处理逻辑,使用前序、中序、后序遍历均可(保证先处理左,再处理右即可)。

  1. 确定递归函数参数和返回值

参数有要遍历的树的根节点,还有一个int型变量来记录最长深度,返回值类型为void。

  1. 确定终止条件

当遇到叶子节点时,比较当前深度与最大深度,更新最大深度和左下角的值。

  1. 确定单层递归逻辑

递归过程要回溯,先递归左子树,再递归右子树

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

迭代法:

迭代法更加简单,使用层序遍历,需要先将右孩子放入,再将左孩子放入,这样保证每一层都是从右往左遍历,最后一个元素即是最后一层最左边的元素

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

112. 路径总和

递归思路:如果是一棵空树,直接返回false;如果当前结点是叶子结点,需要判断从头结点到该叶子结点的和是否等于targetSum,若等于返回true,否则返回false;单层执行逻辑为,递归遍历左子树和右子树,找到就返回true,遍历完还没有找到,说明不存在,返回false。

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

113.路径总和ii

这道题目也顺便做了,与112思路基本一样,只不过113还要回溯数组里的元素。

class Solution {
public:
    int sum=0;
    vector<vector<int>> res;
    void findPath(TreeNode* p,int targetSum,vector<int>& vec){
        if(!p) return;
        if(!p->left&&!p->right){
            if(sum+p->val==targetSum){
                vec.push_back(p->val);
                res.push_back(vec);
                vec.pop_back();
            }
            return;
        }
        if(p->left){
            vec.push_back(p->val);
            sum+=p->val;
            findPath(p->left,targetSum,vec);
            sum-=p->val;
            vec.pop_back();
        }
        if(p->right){
            vec.push_back(p->val);
            sum+=p->val;
            findPath(p->right,targetSum,vec);
            sum-=p->val;
            vec.pop_back();
        }
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<int> vec;
        findPath(root,targetSum,vec);
        return res;
    }
};

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

中序:左中右;后序:左右中

后序遍历的最后一个元素一定是中间元素,再根据这个中间元素值去找到中序遍历里面对应的位置,那么位置左边就是左子树,右边就是右子树;将中序数组切割为左中序和右中序两个数组(左闭右开),再根据左中序的元素个数去将后序数组切割为左后序和右后序(左闭右开),递归调用左中序和左后序找到当前结点的左孩子,递归调用右中序和右后序找到当前结点的右孩子。

注意: 切割数组时一定要严格遵循左闭右开的原则,否则一定会乱。中序数组切割时,区间为[0,index)、[index+1,end);后序数组切割时,区间为[0,leftInorder.size)、[leftInorder.size,end)—>这里要提前去除最后一个元素。

class Solution {
public:
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(postorder.size()==0) return NULL;
        int rootValue=postorder[postorder.size()-1];
        TreeNode* root=new TreeNode(rootValue);
        if (postorder.size() == 1) return root;
        int index=0;
        for(;index<inorder.size();index++){
            if(inorder[index]==rootValue) break;
        }
        vector<int> leftInorder(inorder.begin(),inorder.begin()+index);
        vector<int> rightInoder(inorder.begin()+index+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=buildTree(leftInorder,leftPostorder);
        root->right=buildTree(rightInoder,rightPostorder);
        return root;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值