首先贴上这两道题的题解
//113题解
class Solution {
//搞两个公用list,一个用来输出,一个用来缓存
List<List<Integer>> ans = new ArrayList<>();
List<Integer> temp = new ArrayList<>();
//套娃方法安排
public void fillAns(TreeNode root, int sum){
//三种情况,root为空;root为叶子节点;root为过渡节点
if(root==null) return;
temp.add(root.val);
if(root.left==null&&root.right==null&&sum==root.val){
ans.add(new ArrayList(temp));
//return; 这里不能return,因为还没还缓存
}
fillAns(root.left,sum-root.val);
fillAns(root.right,sum-root.val);
temp.remove(temp.size()-1);
}
public List<List<Integer>> pathSum(TreeNode root, int sum) {
fillAns(root,sum);
return ans;
}
}
//257题解
class Solution {
//搞一个输出list
List<String> ans = new ArrayList<>();
//套娃方法
public void fillAns(TreeNode root,StringBuilder myBuilder){
//三种情况:root为空,为叶子节点,为过度节点
if(root==null) return;
myBuilder.append(root.val);
if(root.left==null&&root.right==null){
ans.add(myBuilder.toString());
return;
}
fillAns(root.left,new StringBuilder(myBuilder+"->"));
fillAns(root.right,new StringBuilder(myBuilder+"->"));
}
public List<String> binaryTreePaths(TreeNode root) {
fillAns(root,new StringBuilder());
return ans;
}
}
这两道题有一个共同点:整一个套娃方法用来做递归,在套娃方法里面,传入的树节点root有三种情况:
1、root为空
2、root满足条件,把缓存路径加入ans中(113题条件为root为叶子节点且root.val与该套娃方法传入的sum相等,257题条件只要求root为叶子节点)
3、root为过渡节点,则自己调用自己,开始套娃
在113题中,缓存值为一个成员变量(就是那个temp),在每个套娃方法的内部对传进来的root做判断,若满足条件则把缓存值存入ans。而成员变量有这样一个特点:每个套娃方法使用的是同一个对象。因此在方法的末尾需要把temp恢复原样,即temp.remove(temp.size()-1)
而在257题中,题目要求输出一个字符串,而且中间还有"->"箭头这种东西。如果依然用成员变量当作缓存就很不方便:List类的对象可以用remove()方法来还原,可是StringBuilder类的对象要怎么还原呢?我不知道它里面最后加进来的元素是一位数还是两位数还是三位数啊?因此就不用成员变量当缓存了,而是在每个套娃方法里面自己new一个对象作为缓存。这样某个套娃方法里面的缓存都是自己的,无论它套的娃怎么折腾都不影响他自己的缓存变量的值。
其他小细节:
257题,如果root满足条件,做完操作之后就可以return了。但是131题不行。因为此时还没有到“恢复缓存”这一步,把temp搞乱套了,这个套娃方法的上一个套娃方法使用的就是错误的缓存
257题箭头加在哪里的问题:只有过渡节点的结尾需要加"->"。所以步骤是:root不为空的话先把值加进去,若为叶子节点就操作,return;若为过度节点才加"->"