题目描述
输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
错误示例
这道题不难的,用典型的回溯法就可以做出来。。。
三下五除二,写了下面的代码:
结果呢,当然是不对的啦。。。
下面进行反思。。。
import java.util.ArrayList;
/**
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>> resList = new ArrayList<>();
backtrack(resList, new ArrayList<Integer>(), root, 0, target);
return resList;
}
/**
resList:最终要返回的结果
tmpList:临时lsit,存放路径(即二叉树某些节点的值)
root:遍历的当前节点。回溯法采用DFS进行遍历。
sum:当前tmpList元素之和
target:目标和
*/
private void backtrack(ArrayList<ArrayList<Integer>> resList, ArrayList<Integer> tmpList, TreeNode root, int sum, int target){
if(sum > target || root == null) return; //错误1:如果 root 真的为 null,下面的 if 代码不会执行。
if(sum == target){
//int i = 0;
//while(tmpList.size() < resList.get(i).size()) i++;
resList.add(new ArrayList(tmpList));
return;
}
tmpList.add(root.val);
sum += root.val;
//错误2:如果sum 已经等于 target,那么下面两行代码会把 tmpList加入到resList当中两次
backtrack(resList, tmpList, root.left, sum, target);
backtrack(resList, tmpList, root.right, sum, target);
tmpList.remove(tmpList.size() - 1);
//错误3:下面的代码没必要,backtrack是值传递
sum -= root.val;
//错误4:依据题意,根节点到叶子节点才叫路径
}
}
AC代码
感觉写的还是很乱。。。
import java.util.ArrayList;
/**
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>> resList = new ArrayList<>();
if(root == null) return resList; // 先判断一下是否为空
backtrack(resList, new ArrayList<Integer>(), root, 0, target);
return resList;
}
private void backtrack(ArrayList<ArrayList<Integer>> resList, ArrayList<Integer> tmpList, TreeNode root, int sum, int target){
//不管三七二十一,先添加了再说。
tmpList.add(root.val);
sum += root.val;
if(sum > target) { //加多了,去掉吧
tmpList.remove(tmpList.size() - 1);
return;
}
//不仅和要满足条件,还要判断是不是叶子节点(也是一个坑)
if(sum == target && root.left == null && root.right == null){
//int i = 0;
//while(tmpList.size() < resList.get(i).size()) i++;
resList.add(new ArrayList(tmpList));
tmpList.remove(tmpList.size() - 1);
return;
}
//如果sum < target,接着遍历当前节点的左右节点,当然,如果当前节点的左右节点为空则没有必要遍历了。
if(root.left != null)
backtrack(resList, tmpList, root.left, sum, target);
if(root.right != null)
backtrack(resList, tmpList, root.right, sum, target);
//回溯。。。
tmpList.remove(tmpList.size() - 1);
//下面的操作已经无所谓了,backtrack是值传递。。。
//sum -= root.val;
}
}