每日一题——二叉树中和为某一值的路径

文章讨论了如何在给定二叉树中判断是否存在一条从根节点到叶节点的路径,其节点值之和等于给定的目标值。提供了两种方法:递归前序遍历和深度优先搜索(DFS)利用堆栈。目标是实现空间复杂度O(n)和时间复杂度O(n)。
摘要由CSDN通过智能技术生成

题目


给定一个二叉树root和一个值 sum ,判断是否有从根节点到叶子节点的节点值之和等于 sum 的路径。

  • 该题路径定义为从树的根结点开始往下一直到叶子结点所经过的结点
  • 叶子节点是指没有子节点的节点
  • 路径只能从父节点到子节点,不能从子节点到父节点
  • 总节点数目为n

例如:
给出如下的二叉树,sum=22,

返回true,因为存在一条路径 5→4→11→2 的节点值之和为 22

数据范围:

  • 树上的节点数满足 0≤n≤10000
  • 每个节点的值都满足 ∣val∣≤1000

要求:空间复杂度 O(n),时间复杂度 O(n)

进阶:空间复杂度 O(树的高度),时间复杂度 O(n)

参数说明:二叉树类,二叉树序列化是通过按层遍历,#代表这这个节点为空节点,举个例子:

  1
 / \
2   3
   /
  4

以上二叉树会被序列化为 {1,2,3,#,#,4}

示例1

输入:
{5,4,8,1,11,#,9,#,#,2,7},22
返回值:
true

示例2

输入:
{1,2},0
返回值:
false

示例3

输入:
{1,2},3
返回值:
true

示例4

输入:
{},0
返回值:
false

思路1


可以在根节点每次往下一层的时候,将sum减去节点值,最后检查是否完整等于0。遍历的方法可以选取二叉树常用的递归前序遍历,因为每次进入一个子节点,更新sum值以后,相当于对子树查找有没有等于新目标值的路径,因此可以递归求解。

解答代码1


/**
 * struct TreeNode {
 *	int val;
 *	struct TreeNode *left;
 *	struct TreeNode *right;
 *	TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
class Solution {
public:
    /**
     * @param root TreeNode类 
     * @param sum int整型 
     * @return bool布尔型
     */
    bool hasPathSum(TreeNode* root, int sum) {
        // write code here
        if (root == nullptr) {
            // 此时已经递归过了叶子节点,还没找到符合的,返回false
            return false;
        }
        if (root->left == nullptr && root->right == nullptr
            && root->val == sum) {
            // 左右子树都未null,说明该节点为叶子节点,递归到此的val=sum则说明找到了这条路径
            return true;
        }
        // 更新sum值,递归左右子树
        return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val);
    }
};

思路2


使用栈辅助,进行dfs(深度优先搜索)遍历,检查往下的路径中是否有等于sum的路径和。

栈中记录遍历的节点和到该节点的路径和(pair)。

解答代码2


/**
 * struct TreeNode {
 *  int val;
 *  struct TreeNode *left;
 *  struct TreeNode *right;
 *  TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 * };
 */
#include <stack>
class Solution {
  public:
    /**
     * @param root TreeNode类
     * @param sum int整型
     * @return bool布尔型
     */
    bool hasPathSum(TreeNode* root, int sum) {
        // write code here
        if (root == nullptr) {
            return false;
        }
        // 采用dfs遍历
        stack<pair<TreeNode*, int>> stack;// 记录节点和到该节点的路径和
        stack.emplace(root, root->val);// 先将根节点入栈
        while (!stack.empty()) {
            auto now = stack.top();
            stack.pop();

            // 找到叶子结点,判断是否等于目标值
            if (now.first->left == nullptr && now.first->right == nullptr
                    && now.second == sum) {
                return true;
            }

            // 将左右节点入栈,求路径和
            if (now.first->left != nullptr) {
                stack.emplace(now.first->left, now.second + now.first->left->val);
            }
            if (now.first->right != nullptr) {
                stack.emplace(now.first->right, now.second + now.first->right->val);
            }
        }

        return false;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值