(递归是否需要返回值)112.路径总和、113. 路径总和 II

首先给递归是否需要返回值的结论:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii的情况)
  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236.二叉树的最近公共祖先的情况)
  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(112.路径总和的情况)

112.路径总和

题目描述:

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

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

解答:

采用递归加回溯的办法解决。遍历采用先序遍历(中左右)

依旧先考虑递归三要素:

(1)参数和返回值:根节点肯定需要,其次需要一个参数用于保存路径之和,一个参数保存要找的目标和(targetSum)。

此处只需要找出一条满足条件的路径,遇到了符合条件的路径直接返回即可,所以需要返回值。采用bool类型的返回值。

bool PathSum(TreeNode* root, int sum, int targetSum){}

(2)终止条件:遇到叶子节点判断路径和是否满足条件,若满足返回true,否则false

if (root->left == NULL && root->right == NULL){
            if (sum == targetSum)
                return true;
            else 
                return false;
}

(3)内部处理逻辑:因为终止条件是判断叶子节点,所以递归的过程中就不要让空节点进入递归了。递归函数是有返回值的,如果递归函数返回true,说明找到了合适的路径,应该立刻返回。

其中隐含了回溯,再调用函数返回后sum并未发生改变,等同于回溯,但是没有显式表达出来

 代码实现:

class Solution {
public:
    bool PathSum(TreeNode* root, int sum, int targetSum){
        sum += root->val;
        bool left, right;
        if (root->left == NULL && root->right == NULL){
            if (sum == targetSum)
                return true;
            else 
                return false;
        }
        if (root->left){
            left = PathSum(root->left, sum, targetSum);
        }    
        if (root->right){
            right = PathSum(root->right, sum, targetSum);
        }
        if (left || right) return true;
        else return false;  
    }
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL) return false;
        return PathSum(root, 0, targetSum);
    }
};

 精简版代码:

class Solution {
public:
    bool hasPathSum(TreeNode* root, int targetSum) {
        if (root == NULL) 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);
    }
};

113. 路径总和 II

题目描述:

给你二叉树的根节点 root 和一个整数目标和 targetSum ,找出所有从根节点到叶子节点 路径总和等于给定目标和的路径。

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

解答:

依然采用递归法实现,回溯的思路和上一题基本相同,唯一的不同在于此处无须返回值。此处需要遍历完整棵树且不用处理递归返回值,正是开头所提到的第一种情况。

满足条件的路径存储在结果集合中,无需作为返回值返回。

依然考虑递归三要素:

(1)参数和返回值:根节点肯定需要,然后需要一个参数保存当前的路径,其次需要一个参数用于保存满足条件的路径,一个参数保存路径和,一个参数保存要找的目标和(targetSum)。无需返回值。

(2)终止条件:遇到叶子节点比较和targetSum是否相同,相同则存入result中,不同则返回。

(3)内部处理逻辑:与上一题类似,递归调用即可。

代码实现:

class Solution {
public:
    void PathSum(TreeNode* root, vector<int>path, vector<vector<int>>&result, int sum, int targetSum){
        sum += root->val;
        path.push_back(root->val);
        if (root->left == NULL && root->right == NULL){
            if (sum == targetSum)
                result.push_back(path);
            else 
                return ;
        }
        if (root->left){
            PathSum(root->left, path, result, sum, targetSum);
        }    
        if (root->right){
            PathSum(root->right, path, result, sum, targetSum);
        } 
    }
    vector<vector<int>> pathSum(TreeNode* root, int targetSum) {
        vector<vector<int>>result;
        vector<int>path;
        if (root)
            PathSum(root, path, result, 0, targetSum);
        return result;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值