笔者上coursera的数据结构课时碰到了一段算法题,描述如下:
Problem Description
Task. You are given a description of a rooted tree. Your task is to compute and output its height. Recall
that the height of a (rooted) tree is the maximum depth of a node, or the maximum distance from a
leaf to the root. You are given an arbitrary tree, not necessarily a binary tree.
Input Format. The first line contains the number of nodes 𝑛. The second line contains 𝑛 integer numbers
from −1 to 𝑛 − 1 — parents of nodes. If the 𝑖-th one of them (0 ≤ 𝑖 ≤ 𝑛 − 1) is −1, node 𝑖 is the root,
otherwise it’s 0-based index of the parent of 𝑖-th node. It is guaranteed that there is exactly one root.
It is guaranteed that the input represents a tree.
Constraints. 1 ≤ 𝑛 ≤ 105.
Output Format. Output the height of the tree.
基本的把树搭建的算法为:
allocate 𝑛𝑜𝑑𝑒𝑠[𝑛]
for 𝑖 ← 0 to 𝑛 − 1:
𝑛𝑜𝑑𝑒𝑠[𝑖] =new 𝑁𝑜𝑑𝑒
Then, read each parent index:
for 𝑐ℎ𝑖𝑙𝑑_𝑖𝑛𝑑𝑒𝑥 ← 0 to 𝑛 − 1:
read 𝑝𝑎𝑟𝑒𝑛𝑡_𝑖𝑛𝑑𝑒𝑥
if 𝑝𝑎𝑟𝑒𝑛𝑡_𝑖𝑛𝑑𝑒𝑥 == −1:
𝑟𝑜𝑜𝑡 ← 𝑐ℎ𝑖𝑙𝑑_𝑖𝑛𝑑𝑒𝑥
else:
𝑛𝑜𝑑𝑒𝑠[𝑝𝑎𝑟𝑒𝑛𝑡_𝑖𝑛𝑑𝑒𝑥].𝑎𝑑𝑑𝐶ℎ𝑖𝑙𝑑(𝑛𝑜𝑑𝑒𝑠[𝑐ℎ𝑖𝑙𝑑_𝑖𝑛𝑑𝑒𝑥])
计算树高度的方法反而并不是很值得一提,跟二叉树是一致的:
Height(tree)
if tree = nil:
return 0
return 1 + Max(Height(tree.0),Height(tree.1)…Height(tree.i))
原来的构建child关系时,使用的:
for(int j=0;j<n;j++) {
if(Nodes[j].value==vertex) {
Nodes[j].setParent(Nodes[vertex]);
Nodes[vertex].Add(Nodes[j]);
}
非常拖慢性能,导致了多次的grader失败。改为了一步到位的
else
Nodes[Nodes[childindex].value].Add(childindex);
能快一倍左右
import java.util.*;
import java.io.*;
public class tree_height {
class FastScanner {
StringTokenizer tok = new StringTokenizer("");
BufferedReader in;
FastScanner() {
in = new BufferedReader(new InputStreamReader(System.in));
}
String next() throws IOException {
while (!tok.hasMoreElements())
tok = new StringTokenizer(in.readLine());
return tok.nextToken();
}
int nextInt() throws IOException {
return Integer.parseInt(next());
}
}
public class nodes{
int value;
boolean root=false;
//ArrayList<nodes>Children;
ArrayList<Integer> Children;
public nodes(int value, ArrayList<Integer> Children) {
this.value=value;
this.Children=Children;
}
public void Add(int child) {
this.Children.add(child);
}
}
public class TreeHeight {
int n;
int parent[];
nodes Nodes[];
void read() throws IOException {
FastScanner in = new FastScanner();
n = in.nextInt();
//ArrayList []Children=new ArrayList[n];
ArrayList []Children=new ArrayList[n];
Nodes=new nodes [n];
for (int i = 0; i < n; i++) {
Children[i]=new ArrayList<Integer>();
Nodes[i]=new nodes(in.nextInt(),Children[i]);
}
for (int childindex = 0; childindex < n; childindex++) {
if(Nodes[childindex].value==-1) {Nodes[childindex].root=true;
}
else
Nodes[Nodes[childindex].value].Add(childindex);//这里这么写能提升很多性能
}
}
int computeHeight(nodes element) {
// Replace this code with a faster implementation
int height=0;
if(element.Children!=null) {
int C=0;
for(int i=0;i<element.Children.size();i++)
{int temp=(int)element.Children.get(i);
C=computeHeight(Nodes[temp]);
if(C>height) {height=C;}
}
}
else
{return 0;}
// int height = 0;
// for (int i = vertex; i != -1; i = parent[i])
// height++;
// maxHeight = Math.max(maxHeight, height);//这也是一种算法,但是效率不高
return height+1;
}
int result() {
int r=0;
for(int i=0;i<n;i++) {
if(Nodes[i].root) {
r=computeHeight(Nodes[i]);
}
}
return r;
}
}
static public void main(String[] args) throws IOException {
new Thread(null, new Runnable() {
public void run() {
try {
new tree_height().run();
} catch (IOException e) {
}
}
}, "1", 1 << 26).start();
}
public void run() throws IOException {
TreeHeight tree = new TreeHeight();
tree.read();
System.out.println(tree.result());
}
}