LeetCode 112.路径总和

题目描述

给你二叉树的根节点 root 和一个表示目标和的整数 targetSum 。判断该树中是否存在 根节点到叶子节点 的路径,这条路径上所有节点值相加等于目标和 targetSum 。如果存在,返回 true ;否则,返回 false 。

叶子节点 是指没有子节点的节点。

示例 1:

输入:root = [5,4,8,11,null,13,4,7,2,null,null,null,1], targetSum = 22
输出:true
解释:等于目标和的根节点到叶节点路径如上图所示。

示例 2:

输入:root = [1,2,3], targetSum = 5
输出:false
解释:树中存在两条根节点到叶子节点的路径:
(1 --> 2): 和为 3
(1 --> 3): 和为 4
不存在 sum = 5 的根节点到叶子节点的路径。

示例 3:

输入:root = [], targetSum = 0
输出:false
解释:由于树是空的,所以不存在根节点到叶子节点的路径。

提示:

  • 树中节点的数目在范围 [0, 5000] 内
  • -1000 <= Node.val <= 1000
  • -1000 <= targetSum <= 1000

思路

递归法

递归三部曲:

  1. 确定递归函数的参数和返回值。参数:需要二叉树的根节点,还需要一个计数器,这个计数器用来计算二叉树的一条边之和是否正好是目标和,计数器为int型。返回值:bool类型,判断是否存在路径。
  2. 确定终止条件。不要去累加然后判断是否等于目标和,那样代码比较麻烦,可以用递减,让计数器count初始为目标和,然后每次减去遍历路径节点上的数值。如果最后count == 0,同时到了叶子节点的话,说明找到了目标和,返回true。如果遍历到了叶子节点,count不为0,就是没找到,返回false。
  3. 确定单层递归的逻辑。本题递归过程中会遇到不需要的路径,因此需要回溯,遇到了合适的路径要立即返回。本题没有中间节点的处理逻辑,因此前中后序的处理都一样。

代码

C++版:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    // 递归法,回溯
    bool traversal(TreeNode* node,int count){
        // 终止条件,到达叶子节点
        if(node->left==NULL&&node->right==NULL&&count==0){
            return true;
        }
        if(node->left==NULL&&node->right==NULL&&count!=0){
            return false;
        }
        // 防止空指针操作,在递归前判空
        if(node->left){
            count-=node->left->val;
            // 找到了合适的路径,应该立刻返回,包含了回溯
            if(traversal(node->left,count)){
                return true;
            }
            // 回溯
            count+=node->left->val;
        }
        if(node->right){
            count-=node->right->val;
            // 找到了合适的路径,应该立刻返回
            if(traversal(node->right,count)){
                return true;
            }
            // 回溯
            count+=node->right->val;
        }
        return false;

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

Python版:

# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def traversal(self, cur: TreeNode, count: int) -> bool:
        if not cur.left and not cur.right and count == 0: # 遇到叶子节点,并且计数为0
            return True
        if not cur.left and not cur.right: # 遇到叶子节点直接返回
            return False
        
        if cur.left: # 左
            count -= cur.left.val
            if self.traversal(cur.left, count): # 递归,处理节点
                return True
            count += cur.left.val # 回溯,撤销处理结果
            
        if cur.right: # 右
            count -= cur.right.val
            if self.traversal(cur.right, count): # 递归,处理节点
                return True
            count += cur.right.val # 回溯,撤销处理结果
            
        return False
    def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
        if root is None:
            return False
        return self.traversal(root, targetSum - root.val) 

需要注意的地方

1.递归函数是否需要返回值的三种情况:(1)如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(【113.路径总和II】);(2)如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (【236. 二叉树的最近公共祖先】);(3)如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题)

2.用从0累加的方式判断目标和的代码比较麻烦,用递减再判断最后是否为0的方式判断更方便。

3.我的理解:在递归中会遇到不需要的东西时需要回溯。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值