【问题标题】:Diameter of a rooted k-ary tree有根 k-ary 树的直径
【发布时间】:2012-03-30 16:46:02
【问题描述】:

我试图找到一种使用递归的线性时间算法来解决使用邻接列表实现的有根 k 元树的直径问题。一棵树的直径是任何一对叶子之间的最大距离。如果我选择一个根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)。我问你这个算法是否工作正常,如果没有,有什么问题?我试图泛化一个算法来解决二叉树的相同问题,但我不知道它是否是一个很好的泛化。

感谢任何帮助!提前致谢!

【问题讨论】:

  • 什么是 V(大写)?和 Adj[r] 一样吗?
  • 不。 V 是包含树 T 的所有节点的集合。
  • 由于你的 max_{v in V} (...) 不依赖于 r,我假设你是单独计算而不是每次递归。
  • 问题只是高度,我不知道如何递归检查:|

标签: algorithm tree


【解决方案1】:

在树中查找直径的所有操作如下:

  1. 随机选择一个节点A,在该节点上运行BFS,寻找距离A最远的节点。将此节点命名为 S

  2. 现在从 S 开始运行 BFS,找到距离 S 最远的节点,将其命名为 D

SD 之间的路径是树的直径。该算法是 O(n),并且只需两次时间遍历树。证明有点棘手,但并不难。 (你自己试试,或者如果你认为不正确,我稍后再写)。小心我说的是树而不是一般的图表。 (树中没有循环,是连通的)。

【讨论】:

  • 感谢您的回复,我已经找到了使用 BFS 的解决方案,并且我也有证据证明它有效。我正在寻找使用递归的解决方案。我正在尝试收集解决此问题的所有可能方法:)
  • @QAndy,您可以再次对 DFS 使用类似的方法,为什么您只寻找递归?目前我没有时间,但是稍后,我会阅读您的方法并就其正确性发表我的看法。
  • @Dree 您是否还需要链接到使用 BFS 及其证明的解决方案?
  • @Dree 编辑:实际上,我自己实现了代码,所以这只是我想要的证明。
【解决方案2】:

这是我相信您感兴趣的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

【讨论】:

  • 非常感谢!我不太习惯 Python,但我想我已经理解了它的实现。只有一件事:process() 函数返回一对(高度,直径),不是吗?
【解决方案3】:

这是使用 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;
        }
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-05
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    • 2014-01-10
    相关资源
    最近更新 更多