下面的内容怎么样,可以在低级 C 中实现,而不需要任何列表/字典/循环结构,例如哈希表。
- 读取输入数据,存储每个解析的行,并计算出一个节点可以拥有的最大子节点数 M
- 分配 的整数数组
int[] arr_of_ints = new int[n*M]
,并将所有条目初始化为 0。想法是节点 i(其中 1<=i<=n)对应于 M 个整数 arr_of_ints[M*(i-1)] 到 arr_of_ints[M *i],并且这些条目的值是该节点的子节点 - 遍历保存的解析数据,并填写arr_of_ints,计算出哪个节点在顶部
- 分配一个数组
int[] ancestors = new int[n]
,它将存储所有祖先的值 - 最后,从树的顶部开始,使用递归函数向下遍历树,使用数组
ancestors
,这样在每个节点处就不需要遍历树来计算相似节点的数量。你的递归越深,你在数组中越远ancestors
,但是当你到达分支的末端时,这个位置就会展开
据我所知,如果有足够的内存供 arr_of_ints[M*i] 使用,那么它应该尽可能快。
更新:我已经用 C# 编写了我的解决方案的一个版本,见下文,我认为它是 O(n log n)。
class Solution {
static char[] space = new char[] { ' ' };
class FileRow {
public readonly int parent;
public readonly int child;
public FileRow(string str) {
string[] split = str.Split(space);
parent = int.Parse(split[0]); child = int.Parse(split[1]);
}
}
public static void Main(String[] args) {
List<FileRow> inputdata = new List<FileRow>();
StreamReader sr = File.OpenText("inputfile.txt");
String[] split = sr.ReadLine().Split(space);
int n = int.Parse(split[0]), T = int.Parse(split[1]);
int[] arr = new int[n]; // this will record the max num of children
while (!sr.EndOfStream) {
FileRow fr = new FileRow(sr.ReadLine());
arr[fr.parent - 1]++;
inputdata.Add(fr);
}
sr.Close();
int M = 0;
for (int i = 0; i < arr.Length; i++) {
M = Math.Max(M, arr[i]);
arr[i] = 0; // set all arr to zero, for use below in setting up tree
}
int[,] tree = new int[n, M];
Boolean[] not_root_node = new bool[n]; // all entries automatically initialised to false
foreach (FileRow fr in inputdata) {
not_root_node[fr.child - 1] = true; // indicate that node fr.child isn't the root node of the tree
tree[fr.parent - 1, arr[fr.parent - 1]++] = fr.child;
}
int count = 0, node = 0;
for (int i = 0; i < not_root_node.Length; i++) {
if (!not_root_node[i]) {
count++; node = i + 1;
}
arr[i] = 0; // set all arr to zero, for use below in calculating result
}
if (count != 1) throw new Exception("ERROR, root node for tree not unique, count="+count.ToString());
// int node is the root of the tree
int level = 0, result = 0;
int[] ancestors = new int[n];
do {
int j = arr[node - 1];
int nextnode = (j < M ? tree[node - 1,j] : 0);
if (nextnode == 0) {
level--;
if (level >=0) node = ancestors[level];
} else {
ancestors[level++] = node;
arr[node - 1]++;
node = nextnode;
for (int i = 0; i < level; i++) {
if (Math.Abs(ancestors[i] - node) <= T) result++;
}
}
} while (level >= 0);
System.Diagnostics.Trace.WriteLine(result);
}
}