剑指Offer - 九度1520 - 树的子结构
2013-11-30 22:31
274 查看
剑指Offer - 九度1520 - 树的子结构 2013-11-30 22:17
题目描述:
输入两颗二叉树A,B,判断B是不是A的子结构。
输入:
输入可能包含多个测试样例,输入以EOF结束。
对于每个测试案例,输入的第一行一个整数n,m(1<=n<=1000,1<=m<=1000):n代表将要输入的二叉树A的节点个数(节点从1开始计数),m代表将要输入的二叉树B的节点个数(节点从1开始计数)。接下来一行有n个数,每个数代表A树中第i个元素的数值,接下来有n行,第一个数Ki代表第i个节点的子孩子个数,接下来有Ki个树,代表节点i子孩子节点标号。接下来m+1行,与树A描述相同。
输出:
对应每个测试案例,
若B是A的子树输出”YES”(不包含引号)。否则,输出“NO”(不包含引号)。
样例输入:
7 3 8 8 7 9 2 4 7 2 2 3 2 4 5 0 0 2 6 7 0 0 8 9 2 2 2 3 0 0 1 1 2 0 3 0
样例输出:
YES NO
提示:
B为空树时不是任何树的子树。
题意分析: 给定两棵二叉树,判断树B是否为树A的子结构。题目中的输入输出方式有点问题,不过无伤大雅。对于“子结构”的话,可以参考下面的例子:
只要能把B树和A树中的一部分重合起来,就定义B树是A树的子结构。递归求解即可,细节应该不需要赘述了。如果A树、B树的节点数分别为m、n,则时间复杂度O(m * n),因为递归过程中对于每个A中的节点,都需要将B树的结构验证一遍,验证失败时可以提前结束递归,但平均复杂度仍是O(n),所以综合起来是O(m * n)。下面是ac代码。
// 652327 zhuli19901106 1520 Accepted 点击此处查看所有case的执行结果 1048KB 2486B 10MS // 201311162044 #include <cstdio> using namespace std; const int MAXN = 1005; int a[MAXN][3]; int b[MAXN][3]; int c[MAXN]; int na, nb; int ra, rb; bool is_subtree(const int a[][3], const int b[][3], int ia, int ib) { if(a == NULL || b == NULL){ return false; } if(ia < 0 || ia > na - 1){ return false; } if(ib < 0 || ib > nb - 1){ return false; } if(a[ia][0] == b[ib][0]){ bool ret1, ret2; if(b[ib][1] != -1){ ret1 = is_subtree(a, b, a[ia][1], b[ib][1]); }else{ ret1 = true; } if(b[ib][2] != -1){ ret2 = is_subtree(a, b, a[ia][2], b[ib][2]); }else{ ret2 = true; } return (ret1 && ret2); }else{ return false; } } int main() { int i, j; int x, y; while(scanf("%d%d", &na, &nb) == 2){ for(i = 0; i < na; ++i){ for(j = 0; j < 3; ++j){ a[i][j] = -1; } } for(i = 0; i < nb; ++i){ for(j = 0; j < 3; ++j){ b[i][j] = -1; } } for(i = 0; i < na; ++i){ scanf("%d", &x); a[i][0] = x; c[i] = 0; } for(i = 0; i < na; ++i){ scanf("%d", &j); if(j == 1){ scanf("%d", &x); a[i][1] = x - 1; ++c[x - 1]; }else if(j == 2){ scanf("%d%d", &x, &y); a[i][1] = x - 1; a[i][2] = y - 1; ++c[x - 1]; ++c[y - 1]; } } ra = -1; for(i = 0; i < na; ++i){ if(c[i] == 0){ ra = i; } } for(i = 0; i < nb; ++i){ scanf("%d", &x); b[i][0] = x; c[i] = 0; } for(i = 0; i < nb; ++i){ scanf("%d", &j); if(j == 1){ scanf("%d", &x); b[i][1] = x - 1; ++c[x - 1]; }else if(j == 2){ scanf("%d%d", &x, &y); b[i][1] = x - 1; b[i][2] = y - 1; ++c[x - 1]; ++c[y - 1]; } } rb = -1; for(i = 0; i < nb; ++i){ if(c[i] == 0){ rb = i; } } // you can't put this if() up front, if na > 0 && nb == 0, then the input data for a is ignored if(na <= 0 || nb <= 0){ printf("NO\n"); continue; } if(ra == -1 || rb == -1){ // there is at least one invalid tree printf("NO\n"); continue; } for(i = 0; i < na; ++i){ if(is_subtree(a, b, i, rb)){ break; } } if(i < na){ printf("YES\n"); }else{ printf("NO\n"); } } return 0; }
相关文章推荐
- 【剑指Offer面试题】 九度OJ1520:树的子结构
- 剑指OFFER之树的子结构(九度OJ1520) 本地通过
- 剑指OFFER之树的子结构(九度OJ1520)
- 【剑指Offer面试编程题】题目1520:树的子结构--九度OJ
- 【剑指Offer面试编程题】题目1520:树的子结构--九度OJ
- 剑指Offer题目1520:树的子结构
- 剑指Offer - 九度1214 - 丑数
- 剑指Offer - 九度1371 - 最小的K个数
- [九度OnlineJudge][剑指Offer]题目1283:第一个只出现一次的字符
- 剑指Offer - 九度1516 - 调整数组顺序使奇数位于偶数前面
- 【九度OJ1362】|【剑指offer42】左旋转字符串
- *【九度OJ1368】|【剑指offer25】二叉树中和为某一值的路径
- 剑指Offer - 九度1373 - 整数中1出现的次数(从1到n整数中1出现的次数)
- 【剑指Offer学习】【面试题18 :树的子结构】
- 树的子结构(剑指offer18)
- 【剑指offer之题目1510:替换空格 】九度OJ-1510-替换空格
- 剑指offer-17.树的子结构
- 剑指offer 树的子结构
- 剑指offer 面试题18 树的子结构
- 剑指offer 矩形覆盖 树的子结构 二叉树的镜像 数组中重复的数字 第一个只出现一次的字符