[LeetCode] 112.路径总和

本文详细解析了LeetCode112路径总和问题的递归解法,介绍了如何通过递归遍历二叉树寻找目标路径和,包括确定返回值与传入参数、终止条件及单层递归逻辑。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode 112.路径总和

思路

递归

1、确定返回值与传入参数

参数:

  • 1)二叉树的根节点
  • 2)计数器,用于计算路径之和

返回值:

  • 如果需要搜索整颗二叉树不用处理递归返回值,递归函数就不要返回值。
  • 如果需要搜索整颗二叉树且需要处理递归返回值,递归函数就需要返回值。
  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题)

2、终止条件

让计数器初试为目标和,每次减去遍历路径节点上的数值,当计数器值为0,并且到了叶子结点(左右子节点都为NULL),则说明找到了目标和,若遍历到叶子节点时,计数器的值不为0,则说明没找到。

3、确定单层递归逻辑

递归遍历节点的左右子节点,遍历的过程中不能让空节点进入递归,因为终止条件是判断叶子结点。在递归遍历的过程中,需要对计数值进行回溯处理。

代码实现

class Solution {
public:
    bool traversal(TreeNode *node, int sum) {
        if(!node->left && !node->right && sum == 0) return true;	// 遇到叶子节点,并且计数为0
        if(!node->left && !node->right) return false;	// 遇到叶子节点直接返回

        if(node->left) {
            if(traversal(node->left, sum - node->left->val)) return true;	// 递归,处理节点,并回溯,撤销处理
        }

        if(node->right) {
            if(traversal(node->right, sum - node->right->val)) return true;
        }

        return false;
    }

    bool hasPathSum(TreeNode* root, int targetSum) {
        if(root == NULL) return false;

        return traversal(root, targetSum - root->val) ;
    }
};
### LeetCode Hot 100 路径总和 III Java 解决方案 #### 方法一:暴力递归法 此方法通过遍历每一个节点并尝试找到从该节点出发的所有可能路径,判断这些路径的和是否等于目标值。 ```java class Solution { int pathnumber; public int pathSum(TreeNode root, long sum) { if (root == null) return 0; Sum(root, sum); pathSum(root.left, sum); pathSum(root.right, sum); return pathnumber; } public void Sum(TreeNode root, long sum) { if (root == null) return; sum -= root.val; if (sum == 0) { pathnumber++; } Sum(root.left, sum); Sum(root.right, sum); } } ``` 这种方法虽然简单直观,但在处理大规模数据时效率较低。对于某些极端情况下的输入,可能会导致性能问题[^1]。 #### 方法二:优化后的前缀和加哈希表 为了提高算法效率,可以采用前缀和的概念加上哈希表来记录已经访问过的节点及其累积值。这样可以在一次深度优先搜索过程中完成计算,而不需要重复遍历子树。 ```java import java.util.HashMap; public class Solution { private HashMap<Long, Integer> prefixSumCount = new HashMap<>(); public int pathSum(TreeNode root, int targetSum) { prefixSumCount.put(0L, 1); return findPath(root, 0L, targetSum); } private int findPath(TreeNode node, long currentSum, int targetSum) { if (node == null) return 0; // 更新当前累计和 currentSum += node.val; // 计算满足条件的数量 int numPathsToCurrentNode = prefixSumCount.getOrDefault(currentSum - targetSum, 0); // 将当前累计和加入map中 prefixSumCount.put(currentSum, prefixSumCount.getOrDefault(currentSum, 0) + 1); // 继续向下探索左右子树 int leftResult = findPath(node.left, currentSum, targetSum); int rightResult = findPath(node.right, currentSum, targetSum); // 移除当前结点的影响以便回溯到父级调用者处继续其他分支的查找工作 prefixSumCount.put(currentSum, prefixSumCount.get(currentSum) - 1); return numPathsToCurrentNode + leftResult + rightResult; } } ``` 这种改进的方法不仅提高了时间复杂度至 O(n),而且空间上也更加高效,适用于更广泛的情况[^2]。 #### 数据约束说明 题目规定了二叉树中的节点数量范围以及各节点取值区间: - 二叉树的节点个数的范围是 [0,1000] - `-10^9 <= Node.val <= 10^9` - `-1000 <= targetSum <= 1000` 因此,在实现解决方案时需要注意数值类型的选取以防止溢出等问题的发生[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夜来疯

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值