问题描述:
输入一颗二叉树的跟节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。(注意: 在返回值的list中,数组长度大的数组靠前)
基本思路:
二叉树的路径问题,基于二叉树的遍历。也就是说既可以是递归形式也可以是非递归形式。
- 递归解决方案
- 以下是非递归方案:
以下三点是主要考虑的问题。
- 因为要计算路径上数的和,使用先序遍历明显是最佳方案。
- 在遍历过程中需要记录路径,这里引入一个List 用来记录路径
使用LinkedList
更合适,原题使用的是ArrayList
,所以这里采用ArrayList
- 常规先序遍历是把节点的右节点压入栈,这里是把含有右子树的节点压入栈。
目的是为了方便回溯。回溯条件是栈顶节点 == 路径队列尾节点
代码的骨架是先序非递归遍历。只是在回溯的时候需要稍加注意
import java.util.*;
public class Solution {
public ArrayList<ArrayList<Integer>> FindPath(TreeNode root, int target) {
ArrayList<ArrayList<Integer>> ans = new ArrayList<>(); // 所有合格路径集合
Stack<TreeNode> nStack = new Stack<>(); // 用于回溯的栈
ArrayList<TreeNode> paths = new ArrayList<>(); // 用于记录路径的队列
TreeNode index = root; //当前节点
int current = 0; // 当前路径的和
while (index != null || nStack.size() != 0) {
current = current + index.val; // 计算路径和
paths.add(index); // 更新路径
// 如果该节点合格,添加到路径集合中
if (index.right == null && index.left == null && current == target) {
ArrayList<Integer> list = new ArrayList<>();
for (TreeNode t : paths) {
list.add(t.val);
}
ans.add(list);
}
if (index.right != null)
nStack.push(index); // 注意这里区别于传统的先序遍历
// 访问左子树
if (index.left != null) {
index = index.left;
} else if (!nStack.isEmpty()) {
index = nStack.pop();
// 核心:路径回溯
while (paths.get(paths.size() - 1) != index) {
current -= paths.get(paths.size() - 1).val;
paths.remove(paths.size() - 1);
}
index = index.right;
} else {
index = null;
}
}
return ans;
}
}