二叉树中和为某一值的路径
题目描述
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
public class Solution {
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
}
}
错误思路
错误代码
ArrayList<ArrayList<Integer>> lists = new ArrayList<ArrayList<Integer>>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root,int target) {
ArrayList<Integer> list = new ArrayList<Integer>();
if(root == null) return null;
if(root.val <= target){
target = target - root.val;
list.add(root.val);
}
while(root.left != null || root.right != null){
if(root.left != null){
FindPath(root.left,target);
}
if(root.right != null){
FindPath(root.right,target);
}
}
if(target == 0) lists.add(list);
return lists;
}
/**
* 2493658==
2493658==
2493658==
*/
错误分析
只是想当然的按照人为的思想在分析,却没有一步一步根据实际情况进行分析,并且在遍历整个树的时候没有真正按照前序遍历的方式去分析,同时后来知道了节点重复的时候,也没有考虑到用一个辅助栈来表示路径。而是想当然的去重新还原root的值,而没有考虑到只需要把当前多余的子节点删掉即可
所以以后尽量一步一步先找到基本的方法,然后按照程序执行的步骤依次展现出来整个过程,从而发现其中的规律
正确思路
确定一个遍历方式:前序遍历(这里也只能前序遍历,因为必须先访问根节点,要从根节点出发)
步骤 | 访问 | 是否为子节点 | 队列 | target |
---|---|---|---|---|
1 | 2 | no | 2 | 2 |
2 | 4 | no | 2,4 | 6 |
3 | 9 | yes | 2,4,9 | 15(加入lists) |
4 | 4(重新回到根节点) | no | 2,4 | 6 |
5 | 3 | no | 2,4,3 | 9 |
6 | 6 | yes | 2,4,3,6 | 15(加入list) |
7 | 3(重新回到根节点) | no | 2,4,3 | 9 |
8 | 7 | yes | 2,4,3,7 | 16 |
9 | 3(重新回到根节点) | no | 2,4,3 | 9 |
10 | 4(重新回到根节点) | no | 2,4 | 6 |
11 | 2(重新回到根节点) | no | 2 | 2 |
12 | 5 | no | 2,5 | 7 |
13 | 8 | yes | 2,5,8 | 15(加入list) |
14 | 遍历结束 |
那么按照上面的思想我们再重新编辑代码:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
public class Test7 {
ArrayList<ArrayList<Integer>> lists = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list = new ArrayList<Integer>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
if(root == null) return null;
if(root.val <= target){
target = target - root.val;
list.add(root.val);
}
if(root.left != null){
FindPath(root.left,target);
}
if(root.right != null){
FindPath(root.right,target);
}
if(target == 0){
ArrayList<Integer> listCopy = new ArrayList<Integer>();
listCopy.addAll(list);
lists.add(listCopy);
list.remove(list.size()-1);
}else {
if(list.size() > 1){
list.remove(list.size()-1);
}
}
return lists;
}
public static void main(String[] args){
TreeNode root = new TreeNode(2);
root.left = new TreeNode(4);
root.right = new TreeNode(5);
root.left.left = new TreeNode(9);
root.left.right = new TreeNode(3);
root.left.right.left = new TreeNode(6);
root.left.right.right = new TreeNode(7);
root.right.right = new TreeNode(8);
Test7 t = new Test7();
ArrayList<ArrayList<Integer>> lists = t.FindPath(root,15);
for(ArrayList<Integer> l : lists){
for(int i = 0; i < l.size(); i++){
System.out.print(l.get(i));
}
System.out.println("==");
}
}
public static class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
}
这个版本针对上面的二叉树是可以实现的,但是运行的时候发现,通过的运行测试为18.6%😂,
根据提示又重新设计了一个测试用例,发现添加root的条件有问题,因为后面返回到根节点的时候不管target是否满足条件都是是一定会删除最后一个叶节点的,所以root的添加是不需要条件的,就相当于是访问一个就添加一个,这也符号前面表格里面的分析规则,分析好了居然没按照步骤来做😭
下面的测试用例的二叉树如下
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
public class Test7 {
ArrayList<ArrayList<Integer>> lists = new ArrayList<ArrayList<Integer>>();
ArrayList<Integer> list = new ArrayList<Integer>();
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
if(target == 0) return lists;//注意这里target为0是返回lists也就是一个空数组,而不是返回null
if(root == null) return null;
target = target - root.val;//删除添加root的条件
list.add(root.val);
if(root.left != null){
FindPath(root.left,target);
}
if(root.right != null){
FindPath(root.right,target);
}
if( target == 0 && root.left == null && root.right == null){
ArrayList<Integer> listCopy = new ArrayList<Integer>();
listCopy.addAll(list);
lists.add(listCopy);
list.remove(list.size()-1);
}else {
if(list.size() > 1){
list.remove(list.size()-1);
}
}
return lists;
}
public static void main(String[] args){
TreeNode root = new TreeNode(10);
root.left = new TreeNode(5);
root.right = new TreeNode(12);
root.left.left = new TreeNode(4);
root.left.right = new TreeNode(7);
// root.left.right.left = new TreeNode(6);
// root.left.right.right = new TreeNode(7);
// root.right.right = new TreeNode(8);
Test7 t = new Test7();
ArrayList<ArrayList<Integer>> lists = t.FindPath(root,15);
for(ArrayList<Integer> l : lists){
for(int i = 0; i < l.size(); i++){
System.out.print(l.get(i));
}
System.out.println("==");
}
}
public static class TreeNode {
int val = 0;
TreeNode left = null;
TreeNode right = null;
public TreeNode(int val) {
this.val = val;
}
}
}
同时还要注意root为null和target为null的特殊情况分别返回什么
欢迎关注我的公众号:小秋的博客
CSDN博客:https://blog.csdn.net/xiaoqiu_cr
github:https://github.com/crr121
联系邮箱:rongchen633@gmail.com
有什么问题可以给我留言噢~