LeetCode题解 二叉树(八):404 左叶子之和;513 找树左下角的值;112 路径总和;113 路径总和II

二叉树

404 左叶子之和 easy

左叶子结点也好判断,若某结点属于左结点,且无子树,就是左叶子结点

即也如此,所以如果要判断,必然要从父结点下手,涉及到三层结点的处理

如果要使用递归法,要使用后序遍历(左右中),从下往上进行累加,代码如下:

int sumOfLeftLeaves(TreeNode* root) {
    if (!root) return 0;
    int leftValSum = 0;
    if (root->left && !root->left->left && !root->left->right)
        leftValSum += root->left->val;
    return leftValSum + sumOfLeftLeaves(root->left) + sumOfLeftLeaves(root->right);

之所以看不出来后序遍历的痕迹,是因为左右中写在一起,做return的结果。

而迭代法,则前中后三种写法皆可,此处以前序遍历为例,代码如下:

int sumOfLeftLeaves(TreeNode* root) {
    stack<TreeNode*> stk;
    if (root) stk.push(root);
    int res = 0;

    while (!stk.empty()) {
        TreeNode* cur = stk.top();
        stk.pop();
        if (cur->left && !cur->left->left && !cur->left->right)
            res += cur->left->val;
        if (cur->left) stk.push(cur->left);
        if (cur->right) stk.push(cur->right);
    }

    return res;
}

利用这道题,顺道回顾一下前序遍历的统一写法,即标记法:

int sumOfLeftLeaves(TreeNode* root) {
    stack<TreeNode*> stk;
    int res = 0;
    if(!root) return res;
    stk.push(root);
    while (!stk.empty()) {
        TreeNode *cur = stk.top();
        if (cur) {
            stk.pop();
            if (cur->right) stk.push(cur->right);
            if (cur->left) {
                stk.push(cur->left);
                if (!cur->left->left && !cur->left->right)
                    res += cur->left->val;
            }
            stk.push(cur);
            stk.push(nullptr);
        }
        else {
            stk.pop();
            cur = stk.top();
            stk.pop();
        }
    }

    return res;
}

513 找树左下角的值 medium

树左下角,在这道题中的意思是最底层的最左边结点,因为示例2如下图所示:

513.找树左下角的值1

所以这道题用层序遍历,会极其方便,因为只需要记录最后一行的第一个结点即可,代码如下:

int findBottomLeftValue(TreeNode* root) {
    queue<TreeNode*> que;
    if (root) que.push(root);
    int res = 0;

    while (!que.empty()) {
        int size = que.size();
        for (int i = 0; i < size; i++) {
            TreeNode* cur = que.front();
            que.pop();
            if (i == 0) res = cur->val;
            if (cur->left) que.push(cur->left);
            if (cur->right) que.push(cur->right);
        }
    }

    return res;
}

这道题也可以用递归法求解,关键在于记录深度,以及如何记录下最后一行的最后一个结点,终止条件就自然是,先满足叶子结点,再判断深度是否为最大深度,如果是,就保存并退出。

int maxDepth = INT_MIN;
int res = 0;
void reversal (TreeNode* cur, int depth) {
    if (!cur->left && !cur->right) {
        if (depth > maxDepth) {
            maxDepth = depth;
            res = cur->val;
        }
        return;
    }
    if (cur->left) {
        reversal(cur->left, depth + 1);
    }
    if (cur->right) {
        reversal(cur->right, depth + 1);
    }
    return;
} 
int findBottomLeftValue(TreeNode* root) {
    reversal(root, 0);
    return res;
}

112 路径总和 easy

要判断是否存在一条根结点到叶子结点的路径之和,等于目标和

必然要用到深度遍历,且递归更加方便一些,要用到回溯的思想,

对于这道题,返回类型是布尔类型,传入参数必然有结点,路径之和,既然要与目标和比较,不如传入与目标值的差值,直至结果为0就自然等于目标和

终止条件自然是叶子结点与是否等于目标和()

bool reversal(TreeNode* cur, int sub) {
    if (!cur->left && !cur->right && sub == 0) return true;
    if (!cur->left && !cur->right) return false;
    if (cur->left) {
        sub -= cur->left->val;
        if (reversal(cur->left, sub)) return true;
        sub += cur->left->val;
    }
    if (cur->right) {
        sub -= cur->right->val;
        if (reversal(cur->right, sub)) return true;
        sub += cur->right->val;
    }
    return false;
}

bool hasPathSum(TreeNode* root, int targetSum) {
    if (!root) return false;
    return reversal(root, targetSum - root->val);
}

精简后的代码如下:

bool hasPathSum(TreeNode* root, int targetSum) {
    if (root == nullptr) return false;
    if (!root->left && !root->right && targetSum == root->val)
        return true;
    return hasPathSum(root->left, targetSum - root->val) || hasPathSum(root->right, targetSum - root->val);
}

使用迭代法,栈里一个元素不仅要记录该节点指针,还要记录从头结点到该节点的路径数值总和

bool haspathsum(TreeNode* root, int sum) {
    if (root == null) return false;
    // 此时栈里要放的是pair<节点指针,路径数值>
    stack<pair<TreeNode*, int>> st;
    st.push(pair<TreeNode*, int>(root, root->val));
    while (!st.empty()) {
        pair<TreeNode*, int> node = st.top();
        st.pop();
        // 如果该节点是叶子节点了,同时该节点的路径数值等于sum,那么就返回true
        if (!node.first->left && !node.first->right && sum == node.second) return true;

        // 右节点,压进去一个节点的时候,将该节点的路径数值也记录下来
        if (node.first->right) {
            st.push(pair<TreeNode*, int>(node.first->right, node.second + node.first->right->val));
        }

        // 左节点,压进去一个节点的时候,将该节点的路径数值也记录下来
        if (node.first->left) {
            st.push(pair<TreeNode*, int>(node.first->left, node.second + node.first->left->val));
        }
    }
    return false;
}

113 路径总和II medium

这道题就不是找到一条了,而是找出所有,使用递归法也简单,只需要多添一个数组,记录路径上所遇结点值即可,另外也要对该数组进行回溯处理

vector<vector<int>> res;
vector<int> vec;

void recursive(TreeNode *cur, int count) {
    if (!cur->left && !cur->right && count == 0) {
        res.push_back(vec);
        return;
    }
    if (!cur->left && !cur->right) 
        return;

    if (cur->left) {
        vec.push_back(cur->left->val);
        count -= cur->left->val;
        recursive(cur->left, count);
        count += cur->left->val;
        vec.pop_back();
    }
    if (cur->right) {
        vec.push_back(cur->right->val);
        count -= cur->right->val;
        recursive(cur->right, count);
        count += cur->right->val;
        vec.pop_back();
    }
    return ;
}

vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
    if (!root) return res;
    vec.push_back(root->val);
    recursive(root, targetSum - root->val);

    return res;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值