Path Sum

2018, Aug 16    

问题描述

给出一棵二叉树以及一个总和 sum,判断这棵二叉树中,是否存在一条从根节点到叶子树节点的路径,其路径上所有节点的值之和正好等于这个 sum

例如,给出下图所示的二叉树,以及 sum = 22

      5
     / \
    4   8
   /   / \
  11  13  4
 /  \      \
7    2      1

我们应当返回 true,因为路径 5->4->11->2 之和正好为 22。

解决思路

这里看到题目跟树有关,首先应当想到使用递归。而递归分两种(可以参考leetcode 的文章):

  • 自顶向下(top-down):如果根据参数就能知道当前节点的答案,并且通过该参数和该答案能够决定给孩子节点传什么参数,那么就用自顶向下。说白了,就是当前节点的答案可以立即给出,并且可以间接帮助其孩子节点算出答案的,我们就用 top-down。
  • 自底向上(bottom-up):如果知道孩子的答案,就能算出当前节点的答案,就用自底向上。

很显然,我们不可能立即给出当前节点的答案,给出树的根节点,我们仅仅知道根节点的值。那么就应该考虑使用 bottom-up 了。

仍然以例子中的二叉树为例:

      5
     / \
    4   8
   /   / \
  11  13  4
 /  \      \
7    2      1

当我们知道根节点的值为 5 时,如果根节点的左子树或者右子树中的任意一棵,存在一个 path sum = 22 - 5 = 17, 那么我们用这个 path sum 加上 5 就等于最终的总和 22,是不是就说明存在 path sum 了呢?也就是说,知道孩子的答案,再根据当前节点的值,就能算出当前节点的答案(是否有 path sum),于是代码就可以很自然地写出来了:

class Solution {
public:
    bool hasPathSum(TreeNode* root, int sum) {
        if (root == NULL) {
            return false;
        }
        int remain = sum - root->val;
        bool isLeaf = (root->left == NULL) && (root->right == NULL);
        bool leftAns = hasPathSum(root->left, remain);
        bool rightAns = hasPathSum(root->right, remain);
        return (leftAns || rightAns || (isLeaf && remain == 0));
    }
};

同时,这段简单的代码也达到了很高的执行效率(4ms),运行速度超过了 leetcode 中该题目下的所有 C++ 提交。