算法训练day18||404.左叶子之和|513.找树左下角的值|112. 路径总和|

404.左叶子之和

思路:

求出左叶子之和的关键在求叶子结点的条件,并且这是左叶子节点,但是在当前节点的时候无法确定自己是不是左叶子结点,所以求左叶子结点,一定要通过操作该结点的父节点。

513.找树左下角的值

给定一个二叉树,在树的最后一行找到最左边的值。

注意点是这个最左边的值不一定是左孩子的值,还可能是右孩子的值

思路:

使用迭代法,层序遍历很简单。

递归法也可以,递归法使用前中后序遍历都可以,关键点在于先访问左子节点,再访问右子节点,求深度,深度最大一层的最先访问到的节点就是树最底层最左边的节点。

代码展示

/**
 * 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:
    int maxDepth=INT_MIN;
    //最大深度==INT_MIN;
    int result;//result用于统计最深层的叶子最左边的叶子结点
    void traversal(TreeNode* node,int depth){
        //递归终止条件 当遇到叶子结点的时候,比较是不是最大深度
        if(node->left==nullptr&&node->right==nullptr){
            if(depth>maxDepth){
                //如果深度大于最大深度
                maxDepth=depth;
                result=node->val;
            }
            return ;
        }
        if(node->left){
            depth++;
            traversal(node->left,depth);
            depth--;
        }
        if(node->right){
            depth++;
            traversal(node->right,depth);
            depth--;
        }
        return ; 
    }
    int findBottomLeftValue(TreeNode* root) {
        traversal(root,1);
        return result; 
        //递归求左下角节点
    }
};

112. 路径总和

思路:对二叉树运用前序遍历,用一个count(count=count-当前节点的值)作为计数器,一直遍历到叶子结点,如果遍历到当前叶子结点时计数器count=0,遍历结束,return true.如果计数器count!=0,那么就向上回溯,返回上一个结点,并且将count也返回上一个节点时候的值,

注意: 这里不需要遍历完整个二叉树,只需要遍历到满足条件的路径就可以了,所以递归函数需要返回值,作为停止遍历的标志,当遇到return true,递归操作停止。

/**
 * 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) {
        if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
        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==nullptr) return false;
        return traversal(root,targetSum-root->val);
    }
};

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

思路:

1.如果后序数组的大小等于0时,return null

2.将后序数组的最后一个元素取出,判断如果后续数组只有一个元素就return 取出的元素。

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* buildTree(vector<int>& inorder, vector<int>& 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 index=0;
         for(index=0;index<postorder.size();index++){
             if(inorder[index]==rootValue) break;
         }
         //找到了切割的点,进行切割中序数组,坚持左闭右开的原则
         vector<int> leftInOrder(inorder.begin(),inorder.begin()+index);
         vector<int> rightInOrder(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(rightInOrder,rightPostorder);
        return root;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值