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

题目:513. 找树左下角的值 - 力扣(LeetCode)

思路:

        非递归:采用层序遍历的方式,遍历到最后一层的第一个节点就是最底层的最左侧节点。定义一个变量result用来记录每一层的第一个节点,在遍历每一层节点时,不断更新result,直到最后一层result里保存的就是最底层的最左侧节点的值。

代码:

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> que;
        int result = 0;
        if(root == NULL) return 0;
        que.push(root);
        while(!que.empty()){
            int size = que.size();
            for(int i = 0; i < size; i++){
                TreeNode* node = que.front();
                que.pop();
                if(i == 0) result = node->val;//每遍历一层,最左侧的节点的值都刷新一次,直到找到最后一层的最左侧节点,然后退出while循环
                if(node->left) que.push(node->left);
                if(node->right) que.push(node->right);
            }
        }
        return result;
    }
};

递归:

题目:112. 路径总和 - 力扣(LeetCode)

思路:递归遍历+回溯

返回值:bool类型,需要一层层返回目标和是否满足路径总和

终止条件:定义一个count变量初始值为目标和,每次减去遍历路径节点上的数值,当遍历到叶子节点并且count == 0时,说明找到一条路径满足目标和,返回true,如果遍历到叶子节点且不等于0,返回false

单层递归逻辑:因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。

递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。

代码:

class Solution {
public:
    bool getSum(TreeNode* cur, int count){
        if(cur->left == NULL && cur->right == NULL && count == 0) return true;
        if(cur->left == NULL && cur->right == NULL && count != 0) return false;
        if(cur->left){//左
            count -= cur->left->val;//递归处理节点,count传递给下一个节点的值应该等于当前count值减去下一个节点的值,因为最后来到叶子节点是判断count是否等于0而不是等于当前节点的值
            if(getSum(cur->left, count)) return true;
            count += cur->left->val;//回溯,count要回到上一个节点的值,再传递到下一个右孩子
        }
        if(cur->right){//右
            count -= cur->right->val;
            if(getSum(cur->right, count)) return true;
            count += cur->right->val;//回溯
        }
        //中
        return false;

    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        return root == NULL ? false : getSum(root, targetSum - root->val);
    }
};

题目:113. 路径总和 II - 力扣(LeetCode)

思路:

返回值:void,因为不需要向上层返回什么信息,只需要一路收集元素,添加到path数组里

终止条件: 定义一个count变量初始值为目标和,每次减去遍历路径节点上的数值,当遍历到叶子节点并且count == 0时,说明找到一条路径满足目标和,就把这条路径加入到二维数组result里,result用来记录所有满足目标和的路径的情况。

单层递归逻辑:把路径上的元素都加入到path数组里,并且回溯count和path

代码:
 

class Solution {
public:
    vector<vector<int>> result;//定义一个二维数组全局变量,用来收集所有的路径和的情况
    vector<int> path;//定义一个一维数组用来收集一条路径上的元素
    void traversal(TreeNode* cur, int count){
        if(cur->left == NULL && cur->right == NULL && count == 0){
            result.push_back(path);//当遍历到叶子节点并且满足和为目标和时,此时path数组已经把这条路径上的元素都收集到了,因此把这条路径加入到result里
            return;//不用向上一层返回信息,只做收集处理,因此返回空
        }
        if(cur->left == NULL && cur->right == NULL && count != 0) return;
        if(cur->left){//左
            path.push_back(cur->left->val);
            count -= cur->left->val;
            traversal(cur->left, count);//递归处理
            count += cur->left->val;//第一次回溯,处理count
            path.pop_back();//第二次回溯,处理path数组里的元素
        }
        if(cur->right){//右
            path.push_back(cur->right->val);
            count -= cur->right->val;
            traversal(cur->right, count);
            count += cur->right->val;
            path.pop_back();
        }
        return;
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        result.clear();
        path.clear();
        if(root == NULL) return result;
        path.push_back(root->val);//先将头结点的值传入path数组里
        traversal(root, targetSum - root->val);//目标和先要减去头结点的值
        return result;
    }
};

题目:106. 从中序与后序遍历序列构造二叉树 - 力扣(LeetCode)

思路:

        首先回忆一下如何根据两个顺序构造一个唯一的二叉树,相信理论知识大家应该都清楚,就是以 后序数组的最后一个元素为切割点,先切中序数组,根据中序数组,反过来再切后序数组。一层一层切下去,每次后序数组最后一个元素就是节点元素。

  • 第一步:如果数组大小为零的话,说明是空节点了。

  • 第二步:如果不为空,那么取后序数组最后一个元素作为节点元素。

  • 第三步:找到后序数组最后一个元素在中序数组的位置,作为切割点

  • 第四步:切割中序数组,切成中序左数组和中序右数组 (顺序别搞反了,一定是先切中序数组)

  • 第五步:切割后序数组,切成后序左数组和后序右数组

  • 第六步:递归处理左区间和右区间

 具体分析见:代码随想录 (programmercarl.com)

代码:

class Solution {
public:
    TreeNode* traversal(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;
        for(index = 0; index < inorder.size(); index++){
            if(inorder[index] == rootValue) break;
        }

        //切割中序数组,区间左闭右开
        //左中序[0, index)
        vector<int> leftinorder(inorder.begin(), inorder.begin() + index);
        //右中序[index + 1, end)
        vector<int> rightinorder(inorder.begin() + index + 1, inorder.end());

        //将后序数组中的最后一个元素舍弃
        postorder.resize(postorder.size() - 1);

        //切割后序数组,区间左闭右开
        //左后序[0, leftinorder.size)
        vector<int> leftpostorder(postorder.begin(), postorder.begin() + leftinorder.size());
        //右后序[leftinorder.size, end)
        vector<int> rightpostorder(postorder.begin() + leftinorder.size(), postorder.end());

        //递归处理左子树和右子树
        //递归返回的是左右子树的根节点,每一层返回root,相当于root->root1->root2->root3->NULL
        root->left = traversal(leftinorder,leftpostorder);
        root->right = traversal(rightinorder, rightpostorder);

        return root;//最后返回的是整棵树的根节点

    }
    TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
        if(inorder.size() == 0 || postorder.size() == 0) return NULL;
        return traversal(inorder, postorder);
    }
};

 题目:105. 从前序与中序遍历序列构造二叉树 - 力扣(LeetCode)

 思路:见上一题

代码:

 

class Solution {
public:
    TreeNode* traversal(vector<int>& preorder, vector<int>& inorder){
        if(preorder.size() == 0) return NULL;
        int rootValue = preorder[0];
        TreeNode* root = new TreeNode(rootValue);
        if(preorder.size() == 1) return root;

        int index;
        for(index = 0; index < inorder.size(); index++){
            if(inorder[index] == rootValue) break;
        }

        vector<int> leftInorder(inorder.begin(), inorder.begin() + index);
        vector<int> rightInorder(inorder.begin() + index + 1, inorder.end());

        preorder.erase(preorder.begin());

        vector<int> leftPreorder(preorder.begin(), preorder.begin() + leftInorder.size());
        vector<int> rightPreorder(preorder.begin() + leftInorder.size(), preorder.end());

         root->left = traversal(leftPreorder, leftInorder);
         root->right = traversal(rightPreorder, rightInorder);

        return root;
    }
    TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
        if(inorder.size() == 0 || preorder.size() == 0) return NULL;
        return traversal(preorder, inorder);
    }
};

   

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值