leetcode刷题第十六天:513.找树左下角的值,112. 路径总和,106.从中序与后序遍历序列构造二叉树,

513.找树左下角的值

最后一行的最左边的值。所以目标就是:在树的最后一行找到最左边的值。最后一行:找深度最大的叶子结点;最左边:采用任何顺序的遍历都可以,因为左都在右的左边。

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

需要类里的两个全局变量,maxDepth用来记录最大深度,result记录最大深度最左节点的数值。

2、确定终止条件

遇到叶子节点的时候,就需要统计一下最大的深度了,所以需要遇到叶子节点来更新最大深度。

3、确定单层递归的逻辑

在找最大深度的时候,递归的过程中依然要使用回溯

class Solution {
public:
    int MaxDeep = INT_MIN;
    int result;
    void traversal(TreeNode* root, int deep) {
        if (root->left == NULL && root->right == NULL) {
            if (deep > MaxDeep) {
                MaxDeep = deep;
                result = root->val;
            }
            return;
        }
        if (root->left) {
            deep++;
            traversal(root->left, deep);
            deep--;
        }
        if (root->right) {
            deep++;
            traversal(root->right, deep);
            deep--;
        }
        return;
    }

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

112. 路径总和

本题前中后序都可以,无所谓,因为中节点也没有处理逻辑

1、确定递归函数的参数和返回类型

参数:需要二叉树的根节点,还需要一个计数器

2、确定终止条件

if (!cur->left && !cur->right && count == 0) return true; // 遇到叶子节点,并且计数为0
if (!cur->left && !cur->right) return false; // 遇到叶子节点而没有找到合适的边,直接返回

3、确定单层递归的逻辑

因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。

下面是整体代码:(要注意的是,这个函数没有减去根节点的值,所以在传入目标值的时候要减去根节点的值)。(还要注意:这里的回溯只有在返回false时才起作用,返回true时就不回溯了,因为没必要了,这一点观察代码回溯放置的位置就知道了)。

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

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

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

这里直接使用卡哥的板书:

1、后续数组为0,空节点;

2、后续数组最后一个元素为根节点(遍历过程中就是子树的根节点);

3、寻找中序数组中的这个元素作为切割点,左边是左子树,右边是右子树;

4、切割中序数组

5、切割后序数组

6、递归处理做区间和右区间

板书也截一下,这个很直观,便于理解:

class Solution {
private:
    TreeNode* traversal(vector<int>& inorder, vector<int>& postorder) {
        if (postorder.size() == 0)
            return NULL;
        int rootval = postorder[postorder.size() - 1];
        TreeNode* root = new TreeNode(rootval);
        // 叶子节点
        if (postorder.size() == 1)
            return root;
        // 切割数组
        int delimiterIndex = 0;
        for (delimiterIndex; delimiterIndex < inorder.size();
             delimiterIndex++) {
            if (inorder[delimiterIndex] == rootval)
                break;
        }
        // 这里统一使用左闭右开
        vector<int> leftinorder(inorder.begin(),
                                inorder.begin() + delimiterIndex);
        vector<int> rightinorder(inorder.begin() + delimiterIndex + 1,
                                 inorder.end());

        // postorder 舍弃末尾元素,因为这个元素就是中间节点,已经用过了
        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 = 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);
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值