我正在尝试使用递归来找到线性时间算法,以解决使用邻接列表实现的有根k-ary树的直径问题。树的直径是任何一对叶子之间的最大距离。如果我选择根r
(即度数为> 1的节点),则可以显示直径是同一子树中两片叶子之间的最大距离或两片叶子之间的最大距离通过r
的路径。我对这个问题的伪代码:
Tree-Diameter(T,r)
if degree[r] = 1 then
height[r] = 0
return 0
for each v in Adj[r] do
for i = 1 to degree[r] - 1 do
d_i = Tree-Diameter(T,v)
height[r] = max_{v in Adj[r]} (height[v]
return max(d_i, max_{v in V} (height[v]) + secmax_{v in V} (height[v], 0) + 1)
为了获得线性时间,我同时计算每个子树的直径和高度。然后,我选择每个子树的直径和树的两个最大高度之间的最大数量+ 1(secmax
函数在height[v]
和0
之间选择,因为某些子树可以有只有一个孩子:在这种情况下,第二大的高度是0
)。我问你这个算法是否正常工作,如果没有,有什么问题?我试图概括一种解决二叉树相同问题的算法,但我不知道它是否是一个很好的推广。
任何帮助表示赞赏!提前谢谢!
答案 0 :(得分:4)
在查找直径的所有树中,执行如下操作:
选择一个随机节点 A ,在此节点上运行BFS,从 A 中查找最远的节点。将此节点命名为 S 。
现在从 S 开始运行BFS,从 S 中找到最远的节点,将其命名为 D 。
< / LI> 醇>S 和 D 之间的路径是树的直径。该算法为O(n),只有两次遍历树。证明有点棘手,但并不难。 (尝试自己或如果你认为不对,我会在以后写下来)。小心我说的是树而不是一般图。 (树中没有循环并且已连接)。
答案 1 :(得分:0)
这是我认为你感兴趣的python实现。这里,树被表示为子树列表。
def process(tree):
max_child_height=0
secmax_child_height=0
max_child_diameter=0
for child in tree:
child_height,child_diameter=process(child)
if child_height>max_child_height:
secmax_child_height=max_child_height
max_child_height=child_height
elif child_height>secmax_child_height:
secmax_child_height=child_height
if child_diameter>max_child_diameter:
max_child_diameter=child_diameter
height=max_child_height+1
if len(tree)>1:
diameter=max(max_child_diameter,max_child_height+secmax_child_height)
else:
diameter=max_child_diameter
return height,diameter
def diameter(tree):
height,diameter=process(tree)
return diameter
答案 2 :(得分:0)
这是Java的递归解决方案。
import java.util.ArrayList;
import java.util.List;
public class DiameterOrNAryTree {
public int diameter(Node root) {
Result result = new Result();
getDepth(root, result);
return result.max;
}
private int getDepth(Node node, Result result) {
if (node == null) return 0;
int h1 = 0, h2 = 0;
for (Node c : node.children) {
int d = getDepth(c, result);
if (d > h1) {
h2 = h1;
h1 = d;
} else if (d > h2) h2 = d;
}
result.max = Math.max(result.max, h1 + h2);
return h1 + 1;
}
class Result {
int max;
Result() {
max = 0;
}
}
class Node {
public int val;
public List<Node> children;
public Node() {
children = new ArrayList<Node>();
}
public Node(int _val) {
val = _val;
children = new ArrayList<Node>();
}
public Node(int _val, ArrayList<Node> _children) {
val = _val;
children = _children;
}
}
}