java引用传递(包括容器引用传递)&剑指offer——二叉树中和为某一值的路径

  1. ,这道题目主要让我深刻的了解到引用传递,若把传递进去的引用赋值,函数结束后,还是原来的内容,但是特别注意 :若是容器之类的,它的add操作、remove操作,这不是引用复赋值,而是改变其内容,所以当函数结束时,该引用指向的值则已经改变了。
  2. 然而,这道题还让我了解到更深层次,如下代码,是错误的,无论用例是什么,传出了的ArrayList<ArrayList<Integer>>都为空,是因为每次找到了路径之后,加进来一个路径ArrayList<Integer>,但是后面改变了这个ArrayList<Integer>,则ArrayList<ArrayList<Integer>>里的ArrayList<Integer>也会改变。
import java.util.ArrayList;
import java.util.Stack;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        ArrayList<ArrayList<Integer>> pathList = new ArrayList<ArrayList<Integer>>();
        if(root == null){ //如果此树为空则直接返回
            return pathList;
        }
        Stack<TreeNode> path = new Stack<TreeNode>();//定义栈来存储一条路径
        ArrayList<Integer> a=new ArrayList<Integer>();
        int c=0;
        FindPath(root, target,c, path,a, pathList); //调用查找方法
        return pathList;
    }
    public void FindPath(TreeNode t,int target,int currentSum,Stack<TreeNode> s,ArrayList<Integer> at,ArrayList<ArrayList<Integer>> aat){
        s.push(t);
        currentSum+=t.val;
        at.add(t.val);
        if(t.left==null&&t.right==null&&currentSum==target){
            aat.add(at);
            currentSum-=t.val;
        }
        if(t.left!=null)
            FindPath(t.left,target,currentSum,s,at,aat);
        if(t.right!=null)
            FindPath(t.right,target,currentSum,s,at,aat);
        s.pop();
        at.remove(at.size()-1);
    }
    

}

 正确的代码如下,就在每次找到某条符合的路径的时候,创建一个ArrayList<Integer>,将所有值带进去。

import java.util.ArrayList;
import java.util.Stack;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        ArrayList<ArrayList<Integer>> pathList = new ArrayList<ArrayList<Integer>>();
        if(root == null){ //如果此树为空则直接返回
            return pathList;
        }
        Stack<TreeNode> path = new Stack<TreeNode>();//定义栈来存储一条路径
        int c=0;
        FindPath(root, target,c, path, pathList); //调用查找方法
        return pathList;
    }
    public void FindPath(TreeNode t,int target,int currentSum,Stack<TreeNode> s,ArrayList<ArrayList<Integer>> aat){
        s.push(t);
        currentSum+=t.val;
        
        if(t.left==null&&t.right==null&&currentSum==target){
            //正确代码主要就是下面这一段区别,并且这个递归函数没有ArrayList<Integer>这个形参
            ArrayList<Integer> a=new ArrayList<Integer>();
            for(TreeNode tr:s)
                a.add(tr.val);
            aat.add(a);
        }
        if(t.left!=null)
            FindPath(t.left,target,currentSum,s,aat);
        if(t.right!=null)
            FindPath(t.right,target,currentSum,s,aat);
        s.pop();
        currentSum-=t.val;
    }
    

}

结果如下 

 还有一种将stack里面不放TreeNode,就放Integer,结果如下,空间复杂度和放TreeNode一样

 

原本还想用图的深度遍历来做,即不用递归的方式,但是DFS需要有一个boolean[] 来标记每个节点是否被访问过,但由于二叉树没有节点数这个信息,所以不好用这个方法来做,在这里先不做解答,下面代码是错的,暂时没想到好的方法解决,所以先放这吧

import java.util.ArrayList;
import java.util.Stack;
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
        Stack<TreeNode> s=new Stack<TreeNode>();
        int res=0;
        ArrayList<ArrayList<Integer>> al=new ArrayList<ArrayList<Integer>>();
        if(root==null)
            return al;
        s.push(root);
        ArrayList<Integer> a=new ArrayList<Integer>();
        while(!s.isEmpty()){
            TreeNode p=s.peek();
            res+=p.val;
            a.add(p.val);
            if(p.left==null&&p.right==null){
                if(res==target){
                    al.add(a);
                    res-=p.val;
                }
                a.remove(p);
                s.pop();
            }
            if(p.right!=null)
                s.push(p.right);
            if(p.left!=null)
                s.push(p.left);
            
        }
        return al;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值