【必拿下系列】路径总和112&路径总和113

链接: 路径总和112直达地
链接: 路径总和II113直达地

路径总和112

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

叶子节点 是指没有子节点的节点。
阅读题目所得:是需要求从头结点到叶子节点的所有路径中他们val的和是否有正好等于targetSum的存在
划重点:叶子节点和返回值boolean
思考如下:需要从头结点到叶子节点,那么前序遍历(中左右),中序遍历(左中右),后序遍历(左右中), ,这是肯定的.然后递归or迭代选一个就可以了,还有就是这里面会扯到回溯(大家需要注意).
关于递归(我是使用Carl哥的那三条规则来确定怎么写的)
1.确定递归函数的参数和返回值
2.确定递归的退出条件
3.确定单层递归的逻辑
关于递归是否需要返回值

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。(这种情况就是本文下半部分介绍的113.路径总和ii)
  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 (这种情况我们在236. 二叉树的最近公共祖先
    (opens new window)中介绍)
  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)
    (以上来自carl哥)
    (先埋下伏笔吧,主要是我也没彻底参透)
    递归代码:
class Solution {
    public boolean hasPathSum(TreeNode root, int targetSum){
        //燃烧心火,将对手击溃
        //递归玩法:
        //1.递归函数的参数和返回值
        //参数:root,int left,返回值:boolean
        //2.递归的退出条件
        //当root.left,root.right都等于null
        //3.递归的单层递归逻辑
        if(root==null)return false;
        return travel(root,targetSum);
    }
    private boolean travel(TreeNode root,int left){
        left-=root.val;
        if(root.left==null&&root.right==null&&left==0){
            return true;
        }
        if(root.left==null&&root.right==null){
            return false;
        }
        if(root.left!=null){
            if(travel(root.left,left))return true;
            
        }
        if(root.right!=null){
            if(travel(root.right,left))return true;
        }
        return false;
    }
}

迭代:(当时我是尝试写迭代的,但是没写出来,因为不会迭代的回溯)

public boolean hasPathSum2(TreeNode root, int targetSum){
        //用迭代吧,好久没用迭代了
        //前序遍历,(只要第一个是中就ok,左右或右左问题不大)
        if(root==null)return false;
        //重头戏来了,
        Deque<Pair<TreeNode,Integer>> stack=new LinkedList<>();
        stack.push(new Pair<>(root,targetSum-root.val));
        while(!stack.isEmpty()){
            Pair<TreeNode,Integer> node=stack.pop();//就直接弹了,因为不用返回具体路径
            if(node.getKey().right==null&&node.getKey().left==null&&node.getValue()==0){
                return true;
            }
            if(node.getKey().right!=null){
                stack.push(new Pair<>(node.getKey().right,node.getValue()-node.getKey().right.val));
            }
            if(node.getKey().left!=null){
                stack.push(new Pair<>(node.getKey().left,node.getValue()-node.getKey().left.val));
                //回溯在哪里?
                //在node.getValue()-node.getKey().left.val这里哦
                //比如根节点是1,左是2,右是3,targetsum是5
                //那么如果3-2,不合适时,再访问右节点时可以发现要进去时,填pair<TreeNode,Integer>中
                //Integer的值是3-3,
                //所以我们是利用Integer的值来进行储存回溯时的另一种情况,
                //使得我们可以实现回溯
            }
        }
        return false;
    }

路径总和ii113

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

叶子节点 是指没有子节点的节点。
分析题目:与上题对比,多了要路径(所有),其他基本差不多
这题就不搞迭代什么的了,(太麻烦).
在这一题中我们需要搜索整颗树,同时也不用利用递归来处理返回值,所以就直接返回void吧.
具体捋一下代码逻辑(递归)
1.递归参数,返回值
参数:TreeNode root少不了,还有targetSum,其他的再用全局变量代替吧,返回值:void(既然要void,那就要做好做全局变量的准备)
2.退出条件:
当root.left==null&&root.right==null&&targetSum==0
3.单层递归的逻辑:代码见

class Solution {
    List<List<Integer>> res=new ArrayList<>();
    public List<List<Integer>> pathSum(TreeNode root, int targetSum) {
     //level2的enemy
     //依旧使用递归
     //形参和返回值
     //TreeNode target,void
     //递归的退出条件
     //当root.left&&root.right==null
     //单层递归的逻辑
     if(root==null)return res;
     list.add(root.val);
     getPaths(root,targetSum-root.val);
     return res;
    }
    List<Integer> list=new ArrayList<>();
    public void getPaths(TreeNode root,int left){
        if(root.right==null&&root.left==null&&left==0){
            res.add(new ArrayList<>(list));
            return;
        }
        if(root.right==null&&root.left==null){
            return;
        }
        if(root.left!=null){
            list.add(root.left.val);
            left-=root.left.val;
            getPaths(root.left,left);
            left+=root.left.val;
            list.remove(list.size()-1);
        }
        if(root.right!=null){
            list.add(root.right.val);
            left-=root.right.val;
            getPaths(root.right,left);
            left+=root.right.val;
            list.remove(list.size()-1);
        }
    }
}

给我点个赞,年入破百万

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值