剑指Offer - 九度1368 - 二叉树中和为某一值的路径

时间:2023-03-09 19:15:04
剑指Offer - 九度1368 - 二叉树中和为某一值的路径
剑指Offer - 九度1368 - 二叉树中和为某一值的路径
2013-11-23 03:46
题目描述:

输入一颗二叉树和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

输入:

每个测试案例包括n+1行:

第一行为2个整数n,k(1<=n<=10000),n表示结点的个数,k表示要求的路径和,结点编号从1到n。

接下来有n行。这n行中每行为3个整数vi,leftnode,rightnode,vi表示第i个结点的值,leftnode表示第i个结点的左孩子结点编号,rightnode表示第i个结点的右孩子结点编号,若无结点值为-1。编号为1的结点为根结点。

输出:

对应每个测试案例,先输出“result:”占一行,接下来按字典顺序输出满足条件的所有路径,这些路径由结点编号组成,输出格式参照输出样例。

样例输入:
5 22
10 2 3
5 4 5
12 -1 -1
4 -1 -1
7 -1 -1
1 5
1 -1 -1
样例输出:
result:
A path is found: 1 2 5
A path is found: 1 3
result: 
题意分析:
  题目要求找出从根节点到叶节点的路径之和为指定值的所有路径。思路很清楚:DFS遍历,vector存储路径,sum记录路径和。
  所有节点遍历一次,时间复杂度O(n)。遍历过程中需要存储路径,vector的空间复杂度为O(log(n))。
 // 652977    zhuli19901106    1368    Accepted    点击此处查看所有case的执行结果    1112KB    1552B    30MS
//
#include <cstdio>
#include <vector>
using namespace std; void dfs(const int a[][], const int &n, int r, int sum, int target, vector<int> &path)
{
if(r < || r > n){
return;
} path.push_back(r); if(a[r][] == - && a[r][] == -){
if(sum + a[r][] == target){
// a valid path is found.
printf("A path is found:");
for(int i = ; i < path.size(); ++i){
printf(" %d", path[i]);
}
printf("\n");
}
} if(a[r][] != -){
dfs(a, n, a[r][], sum + a[r][], target, path);
}
if(a[r][] != -){
dfs(a, n, a[r][], sum + a[r][], target, path);
} path.pop_back();
} int main()
{
const int MAXN = ;
int n, i, k, r;
int a[MAXN][];
int c[MAXN];
vector<int> path; while(scanf("%d%d", &n, &k) == ){
for(i = ; i <= n; ++i){
c[i] = ;
}
for(i = ; i <= n; ++i){
scanf("%d%d%d", &a[i][], &a[i][], &a[i][]);
if(a[i][] > ){
++c[a[i][]];
}
if(a[i][] > ){
++c[a[i][]];
}
if(a[i][] > && a[i][] > && a[i][] > a[i][]){
// do this swap to make sure the result is in lexicological order
a[i][] ^= a[i][] ^= a[i][] ^= a[i][];
}
}
r = -;
for(i = ; i <= n; ++i){
if(c[i] == ){
r = i;
break;
}
}
printf("result:\n");
path.clear();
dfs(a, n, r, , k, path);
path.clear();
} return ;
}