题目:
输入一个整数和一棵二元树。从树的根结点开始往下访问一直到叶结点所经过的所有结点形成一条路径。打印出和与输入整数相等的所有路径。
例如输入整数 22 ,如下图二元树:10
/ \
5 12
/ \
4 7
则打印出两条路径:10, 12和10, 5, 7。
思路:
有三种方法:
(1)找出并记录下从根节点到叶子节点的所有路径,对每条路径进行尝试,找到路径上节点和为输入整数的路径。
(2)改造普通二元树为双向二元树,通过指针便可查找相邻的上下级节点。遍历二元树,可找到树上的叶子节点。满足条件路径是叶子到根节点路径的子集。由叶子节点向上查找,当路径上节点和为输入整数,并且到达跟节点时,此路径满足条件。
(3)此方法参考http://blog.youkuaiyun.com/dazhong159/article/details/7906916。算法中涉及递归和回溯。由根节点向叶子节点遍历,记录下遍历路径。当到达叶子节点,并且路径和为输入整数,则此路径满足条件;否则该路径自动废弃。
方法一与方法二思路基本一致,遍历二元树找出所有全通路径,针对每一条计算经过节点的和,找到符合条件的路径。代码实现如下:
//记录所有从根节点到叶子节点的路径
private static List<List<Node>> paths=new ArrayList<List<Node>>();
//获得所有到子节点的路线,记录到path中
private static void getAllPaths(List<Node> path , Node node){
path.add(node);
if(node.getLeft() == null && node.getRight()==null){//node为叶子节点
paths.add(path);
return;
}
Node left = node.getLeft();
if(left != null){
List<Node> leftPath = new ArrayList<Node>();
leftPath.addAll(path);
getAllPaths(leftPath, left);
}
Node right = node.getRight();
if(right !=null){
List<Node> rightPath = new ArrayList<Node>();
rightPath.addAll(path);
getAllPaths(rightPath, right);
}
}
//寻找路径上节点和为sum的路径
private static void getCorrectPath(int sum){
List<List<Node>> corPath = new ArrayList<List<Node>>();
for(List<Node> path : paths){
int total = 0;
for(Node node : path){
total += node.getValue();
}
if(total == sum){
corPath.add(path);
}
}
for(List<Node> path : paths){
for(Node node :path){
System.out.print(node.getValue() + " ");
}
System.out.println();
}
}
方法三核心代码如下:
//sum表示整数值,top为经过路径的节点个数,path用来存放路径节点。
//符合条件的路径满足两个条件:1)sum逐一减去经过节点值后为0。2)节点节点时叶子节点
void findPath(BiTreeNode *root, int sum,int top,int path[])
{
path[top++] = root->data; //所经过节点存入数据路径中
sum -= root->data;
if (root->left == NULL && root->right==NULL)
{
if (sum == 0)
{
printPath(path, top); //满足条件节点,输出路径
}
}
else
{
if (root->left != NULL)
findPath(root->left, sum, top,path);
if (root->right!=NULL)
findPath(root->right, sum, top,path);
}
top --; //回溯,当返回后,路径长度减一
sum += root->data; //sum值回溯
}
方法三成功利用递归函数返回特性,程序走完一条路径后,会自动返回分歧节点,沿另一条路径继续执行,由此可遍历完成所有根节点到叶子节点的路径。当回到分歧节点后,重点是恢复状态值,即sum与path值。此方法通过path记录所经过路径,且对于公共路径进行了重复利用。