【Leetcode程序员面试金典-二叉树】面试题04.10.检查子树 面试题 04.12. 求和路径 (附加一点点递归的总结分析加优化分析)

面试题04.10

1.问题描述

在这里插入图片描述

2.解决方案



面试题04.12

1.问题描述

在这里插入图片描述

2.解决方案

解法一:蛮力法(用回溯法)

在这里插入图片描述

a.分析

1.究极递归双递归的感觉,但是如果能掌握这种强行递归回溯的思路也是个不错的万能解答。
2.思路就是遍历每一个节点,并计算以每一个节点为开始的符合条件的路径的数量,最后将所有节点对应数量相加即得到结果。
3.一个我认为很重要的点在于要清楚每一个递归在递什么,把递归功能也就是函数功能搞清楚了,说白了递归就是个暴力遍历所以我们首先要把题目分析清楚进而分析出我们要实现哪几个功能,每个功能就是一个递归
4.比如以这道题举例,题目要求以任意节点未开始满足条件的路径的条数,那么以任意节点,我们是不是得遍历每一个节点,并对每一个节点计算出一个值,那目标一下清晰了,遍历所有节点是一个递归,对每一个节点求条数是另一个递归,那么分别设计两个递归就是答案了

b.万能模板!!!(根据这道题稍加总结)

1.必要的检查
2.对当前节点进行相应计算
3.递归调用左右节点并得到计算结果
4.相加并返回

//蛮力法(回溯法)
class Solution {
public:
    //返回以root为开始的和为sum的路径的条数
    int getSumWithNode(TreeNode* root,int sum,int curSum){
        //1.必要的检查(因为自己也要被递归调用)
        if(root== nullptr) return 0;

        //2.计算加上当前节点是不是一条符合条件的路径
        int numPath=0;
        curSum+=root->val;
        if(curSum==sum) numPath++;

        //3.递归调用左右并相加
        numPath+=getSumWithNode(root->left,sum,curSum);
        numPath+=getSumWithNode(root->right,sum,curSum);

        //4.返回以root为开始的和为sum的路径的条数
        return numPath;
    }

    //返回以root为根节点的整棵树何为sum的路径的条数
    int pathSum(TreeNode* root, int sum) {
        //1.必要的检查
        if(root== nullptr) return 0;

        //2.以根节点开始路径
        int numRoot=getSumWithNode(root,sum,0);

        //3.以根节点左右节点开始路径
        int numLeft=pathSum(root->left,sum);
        int numRight=pathSum(root->right,sum);

        //4.相加返回
        return numRoot+numLeft+numRight;

    }
};


解法二:蛮力法(用回溯法)–稍做优化

在这里插入图片描述

a.分析

说实话能有这个优化效果我是真么想到一开始!

1.将getSumWithNode(TreeNode* root,int sum,int curSum)这个函数改为了void返>回值,这样一来统计以每个节点为开始的路径的条数变为了累加类变量numPath。
2.之前的写法说实话是对于每一个节点都统计一次并且返回,然后将所有节点都加起来>返回,但是这种算法就是,唉,每个节点我也不管了,反正一直累加,省去了返回值计>算的过程,最后直接返回累加的结果numPath。
3.将原来的第一种代码改为第二种,好像只是省去了自加这一步curSum+=root->val。

		//2.计算加上当前节点是不是一条符合条件的路径
        int numPath=0;
        curSum+=root->val;
        if(curSum==sum) numPath++;

        //3.递归调用左右并相加
        numPath+=getSumWithNode(root->left,sum,curSum);
        numPath+=getSumWithNode(root->right,sum,curSum);
		//2.计算加上当前节点是不是一条符合条件的路径
        //curSum+=root->val;
        if((curSum+root->val)==sum) numPath++;

        //3.递归调用左右并相加
        getSumWithNode(root->left,sum,curSum+root->val);
        getSumWithNode(root->right,sum,curSum+root->val);

4.总结:

a.返回值很耗时间,如果能不用返回值最好别用,尤其递归!
b.尽量别自加运算,而是直接用加法表达式当结果!


b.代码
//蛮力法(回溯法)---优化版
class Solution1 {
public:
    int numPath=0;
    //返回以root为开始的和为sum的路径的条数
    void getSumWithNode(TreeNode* root,int sum,int curSum){
        //1.必要的检查(因为自己也要被递归调用)
        if(root== nullptr) return ;

        //2.计算加上当前节点是不是一条符合条件的路径
        //curSum+=root->val;
        if((curSum+root->val)==sum) numPath++;

        //3.递归调用左右并相加
        getSumWithNode(root->left,sum,curSum+root->val);
        getSumWithNode(root->right,sum,curSum+root->val);

        //4.返回以root为开始的和为sum的路径的条数
        //return numPath;
    }

    //返回以root为根节点的整棵树何为sum的路径的条数
    int pathSum(TreeNode* root, int sum) {
        //1.必要的检查
        if(root== nullptr) return 0;

        //2.以根节点开始路径
        getSumWithNode(root,sum,0);

        //3.以根节点左右节点开始路径
        pathSum(root->left,sum);
        pathSum(root->right,sum);

        //4.相加返回
        //return numRoot+numLeft+numRight;
        return numPath;

    }
};
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值