二叉树中和为某一值的路径(push,pop;add,removeLast;offer,pollLast ) ( 模拟添加完结点后,立马更新target并且判断target是否为0)Leetcode51

13 篇文章 0 订阅
11 篇文章 0 订阅

不使用for循环就可以保证第一个结点永远是根节点

使用for循环可以保证从任意节点开始

递归是线程安全的, 最开始的一条路不返回的话,下一条路永远不会开始

但是在只有一个工作数组的情况下,一条路结束以后要创建数组的副本,来防止下一条路上的操作对前一条路的结果造成污染,如果一条路结束以后不创建当前工作数组的副本并保存起来,那么程序运行结束保存的只是最后一条路的工作数组,前面保存的数组都会同步成和最后一条路上的工作数组一模一样的数组,所以最后会出现所有的数组都是一样的情况

class Solution {
    List<List<Integer>> res;
    public List<List<Integer>> pathSum(TreeNode root, int target) {
//        if(root == null){         // 不用加这一个判断,因为root为空的话,res里面还是空List,正好
//            return null;
//        }

        // (LinkedList)小的 可以冒充 (List)大的
        LinkedList<Integer> tem = new LinkedList<>();// LinkedList可以当做List对象放进去,递归的做法只能在递归函数外面创建容器,然后结合容器复制的技术来防污染
        res = new LinkedList<>();                   // tem 保存一条满足条件的路径, res保存所有的tem
        dfs(root,target,tem);
        return res;
    }

    public void dfs(TreeNode root , int k , LinkedList<Integer> tem){
        if(root == null){
            return;
        }


        tem.add(root.val);  // 必须在 判断 k == 0 之前,进行 k -= root.val; 并将 root.val 加进tem;
        k -= root.val;      // 否则, 就会少了 当前节点val值的贡献
        // 一加进去root.val 接下来就进行判断
        // 加进来这一轮结点的val值了,现在可以判断了
        if(root.left == null && root.right == null){//开始判断
            if(k==0){

                // 递归是线程安全的, 最开始的一条路不返回的话,下一条路永远不会开始
                //这里要创建一个新的List集合,将tem复制一份放进去
                //这样是为了避免分支污染,也就是后续对tem的操作,影响了前面的路径
                //虽然递归不用考虑多线程的影响(它是一条路走到黑的),但是由于递归只能在递归函数之外创建容器,所以我保存多条路径的时候都是用的用一个容器,所以需要创建副本来保证安全,如果不用递归的方法,用迭代的话,我就可以在循环里面new一个新容器,将其保存起来后,这个循环结束,此容器就会自动销毁
                res.add(new LinkedList<>(tem));  // 找到了一条满足条件的路径,创建当前这一条路上工作数组的副本

                //直接res.add(tem);  这样是错的
            }
        }

        dfs(root.left,k,tem);
        dfs(root.right,k,tem);

        tem.removeLast();   // removelast 和 polllast都是从list 的 end移除并返回这个元素  :在队尾操作
                            // add 和 offer 是在 List 的 end 添加元素                   :在队尾操作
                            // push 和 pop 是在 List 的 start 添加 和 移除 元素          :在队首操作


    }





}
class Solution {
    List<List<Integer>> res;
    public List<List<Integer>> pathSum(TreeNode root, int target) {
//        if(root == null){         // 不用加这一个判断,因为root为空的话,res里面还是空List,正好
//            return null;
//        }

        // (LinkedList)小的 可以冒充 (List)大的 , 即 用LinkedList 初始化 List
        LinkedList<Integer> tem = new LinkedList<>();// LinkedList可以当做List对象放进去,递归的做法只能在递归函数外面创建容器,然后结合容器复制的技术来防污染
        res = new LinkedList<>();   // 函数外面定义,函数里面初始化   // tem 保存一条满足条件的路径, res保存所有的tem
        dfs(root,target,tem);
        return res;
    }

    public void dfs(TreeNode root , int k , LinkedList<Integer> tem){
        if(root == null){
            return;
        }


        tem.add(root.val);  // 必须在 判断 k == 0 之前,进行 k -= root.val; 并将 root.val 加进tem;
        k -= root.val;      // 否则, 就会少了 当前节点val值的贡献
        // 一加进去root.val 接下来就进行判断
        // 加进来这一轮结点的val值了,现在可以判断了
        if(root.left == null && root.right == null){//开始判断
            if(k==0){

                // 递归是线程安全的, 最开始的一条路不返回的话,下一条路永远不会开始
                //这里要创建一个新的List集合,将tem复制一份放进去
                //这样是为了避免分支污染,也就是后续对tem的操作,影响了前面的路径
                //虽然递归不用考虑多线程的影响(它是一条路走到黑的),但是由于递归只能在递归函数之外创建容器,所以我保存多条路径的时候都是用的用一个容器,所以需要创建副本来保证安全,如果不用递归的方法,用迭代的话,我就可以在循环里面new一个新容器,将其保存起来后,这个循环结束,此容器就会自动销毁
                res.add(new LinkedList<>(tem));

               // res.add(tem);  //这样是错的
            }
        }

        dfs(root.left,k,tem);
        dfs(root.right,k,tem);

        // 回溯完事之后,返回的时候要撤销当前结点的影响
        tem.removeLast();   // removelast 和 polllast都是从list 的 end移除并返回这个元素  :在队尾操作
                            // add 和 offer 是在 List 的 end 添加元素                   :在队尾操作
                            // push 和 pop 是在 List 的 start 添加 和 移除 元素          :在队首操作


    }





}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

雄狮少年

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

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

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

打赏作者

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

抵扣说明:

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

余额充值