华为2016春招实习生的在线机试题共3道,分值分别为100、200和300。因前两道均十分简单,这里只贴出可能被坑的第三道。
原题如下:
求二叉树的深度
描述:
给出一个字符串形式表达的二叉树,求出指定节点深度。
输入的树形结构字符串格式为:
1、以父节点、左子树、右子树表示的二叉树;每个父节点不会超过两个子节点;
2、树的每一个节点采用单个字母表示;树的层次采用数字表示,树根的层次为1,下一层为2,不会超过9层;
3、字符串以“节点名称 层次数 节点名称 层次数…”的形式出现,同一个父节点下,先出现的为左子树。
例如字符串“a1b2c2d3e3f3”生成一棵如下的树:
a
/ \
b c
/ \ /
d e f
节点a的深度为3,节点b的深度是2,节点f的深度是1
运行时间限制: 无限制
内存限制: 无限制
输入:
一行字符串,表示一个二叉树
一行字符串,一个字符一个节点,输入确保字符不会存在重复节点
输出:
指定节点的深度,如果节点不存在,返回0;整数之间用空格隔开
样例输入:
a1b2c2d3e3f3
ab
样例输出:
3 2
网上有人贴出同样题目,并写出自己的代码。但他们的代码大都存在问题。关键在于题目并没有说按照从根到叶子的顺序输入节点,也没有说是满二叉树。因此那些答案只能过一部分测试样例。因此比较好的方法应当是按照题意建树(这里采用vector二维数组来保存节点),并深搜左子树计算深度。
下面贴出自己代码(通过全部测试):
#include <iostream>
#include <cstring>
#include <vector>
#include <string>
#include <algorithm>
#include <cstdio>
using namespace std;
vector<char> v[11];
int findDepth(int treeLevel, int nodeIndex, int depth) {
if (treeLevel > 9) return depth;
int len = v[treeLevel+1].size();
if (len == 0) return depth;
if (treeLevel <= 9 && nodeIndex*2 < len) {
return findDepth(treeLevel+1, nodeIndex*2, depth+1); // 之前没有加return,结果全错了。可能因为VS2005不支持直接调用一个int型的函数。
} else {
return depth;
}
}
int main() {
string tree, query;
getline(cin, tree);
getline(cin, query);
for (int i = 0; i < 11; i++) v[i].clear();
int len = tree.length();
int maxDepth = 0;
for (int i = 0; i < len; i += 2) { // construct the tree
int index = tree[i+1]-'0';
v[index].push_back( tree[i] );
if (index > maxDepth) maxDepth = index;
}
int len1 = query.size();
int depth;
vector<int> ans;
/* test*/
/*for (int i = 1; i <= maxDepth; i++) {
int l = v[i].size();
for (int j = 0; j < l; j++)
cout << v[i][j] << " ";
cout << endl;
}*/
for (int i = 0; i < len1; i++) {
depth = 0;
for (int j = 1; j <= maxDepth; j++) { // Iterate each level
int tempLen = v[j].size();
for (int k = 0; k < tempLen; k++) { // Iterate each node
if (v[j][k] == query[i]) {
depth = findDepth(j, k, 1);
break;
}
}
}
ans.push_back(depth);
}
int ll = ans.size();
if (ll == 0) return 0;
for (int i = 0; i < ll-1; i++) cout << ans[i] << " ";
cout << ans[ll-1] << endl;
return 0;
}