【问题标题】:Expected maximum path length from the root to a leaf in a tree树中从根到叶子的预期最大路径长度
【发布时间】:2016-01-15 12:05:06
【问题描述】:

假设,我们有一棵树,其中每条边的长度为 1 或 2,概率相等。从根到叶的所有路径都包含相同数量的边。求从根到叶的预期最大路径长度。

一棵树的例子

     *
    / \
   /   \
  *     *

预期的最大路径长度为 1/4 * 1 + 3/4 * 2 = 7/4,边的可能长度为 11、12、21、22,后三个给出最大长度 2,第一个 - 1.

【问题讨论】:

  • 嗯,最大路径长度应始终为 2 * 边数?!还是您在寻找平均路径长度?
  • @maxhb each 的长度可以等于 1 或 2,因此所有边都有可能具有单位长度。
  • 所以 7/4 是上述树的平均长度。据我所知,这对于每个具有 2 条边的二叉树都是如此,因此对于年树的每个“层”都是如此。因此,您要查找的值将是 log2(#terminalNodes)*7/4。对于具有 7 个节点、4 个终端节点和 6 个边的下一个更大的树,这将是 log2(4) * 7/4 = 2* 7/4 = 14/4
  • @maxhb 树可能不是二叉的,也不是满的。

标签: algorithm math tree probability


【解决方案1】:

这可以递归计算,没有太多麻烦。

"""
A distribution is represented as a list of probabilities summing to one.
The probability of outcome i is the entry at position i (zero-based indexing).
"""


def max_distribution(dist1, dist2):
    """
    Given two distributions dist1, dist2, computes the distribution of
    the max of a sample from dist1 and a sample from dist2.
    """
    max_dist = []
    cum1 = 0
    cum2 = 0
    for i in range(max(len(dist1), len(dist2))):
        p1 = dist1[i] if i < len(dist1) else 0
        p2 = dist2[i] if i < len(dist2) else 0
        max_dist.append(cum1 * p2 + p1 * cum2 + p1 * p2)
        cum1 += p1
        cum2 += p2
    return max_dist


def distribution_plus_edge(dist):
    """
    Given a distribution dist, computes the distribution of
    a sample from dist plus an uniform random choice in {1, 2}.
    """
    dist_plus = [0] * (len(dist) + 2)
    for i in range(len(dist)):
        for j in [1, 2]:
            dist_plus[i + j] += 0.5 * dist[i]
    return dist_plus


def expectation(dist):
    """
    Given a distribution dist, returns the expectation.
    """
    return sum(i * p for i, p in enumerate(dist))


def max_path_length_distribution(tree):
    """
    Given a tree represented as a list of the root's subtrees,
    computes the distribution of max path lengths from the root to a leaf.
    """
    dist = [1]
    for child in tree:
        child_dist = distribution_plus_edge(max_path_length_distribution(child))
        dist = max_distribution(dist, child_dist)
    return dist


tree = [[], []]
print(expectation(max_path_length_distribution(tree)))  # 1.75
tree = [[[], []], []]
print(expectation(max_path_length_distribution(tree)))  # 3.25

【讨论】:

    【解决方案2】:

    数据结构

    class Tree
    {
    public:
        Tree() {}
        Tree(std::initializer_list<Tree> children) : m_children(children) {}
        Tree(std::vector<Tree> children) : m_children(children) {}
    
        const std::vector<Tree>& GetChildren() const { return m_children; }
    
    private:
        std::vector<Tree> m_children;
    };
    

    算法

    const int EdgeFirst = 1;
    const int EdgeSecond = 2;
    
    map<int, float> empl_internal(const Tree& t)
    {
        map<int, float> prev;
        prev[0] = 1.f;
    
        for (const auto& c : t.GetChildren())
        {
            map<int, float> current;
    
            for (auto& lpFirst : prev)
            {
                for (auto& lpSecond : empl_internal(c))
                {
                    const bool firstPath = prev[0] == 1;
    
                    if (firstPath)
                    {
                        const float probability = lpSecond.second * 0.5;
                        current[lpSecond.first + EdgeFirst] += probability;
                        current[lpSecond.first + EdgeSecond] += probability;
                    }
                    else
                    {
                        const float probability = lpFirst.second * lpSecond.second * 0.5;
    
                        const int l1 = max(lpFirst.first, lpSecond.first + EdgeFirst);
                        current[l1] += probability;
    
                        const int l2 = max(lpFirst.first, lpSecond.first + EdgeSecond);
                        current[l2] += probability;
                    }
                }
            }
    
            swap(prev, current);
        }
    
        return prev;
    }
    
    float empl(const Tree& t)
    {
        float expected = 0;
        for (const auto& a : empl_internal(t))
        {
            expected += a.first * a.second;
        }
    
        return expected;
    }
    

    测试

    int main()
    {
        cout << empl(Tree{}) << endl;
        cout << empl(Tree{ {} }) << endl;
        cout << empl(Tree{ {}, {} }) << endl;
        cout << empl(Tree{ { {}, {} }, {} }) << endl;
        cout << empl(Tree{ {}, {}, {} }) << endl;
        cout << empl(Tree{ { {} }, { {} } }) << endl;
    
        cin.get();
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-02-28
      • 2011-10-31
      • 2014-02-05
      • 1970-01-01
      • 2014-02-24
      • 2010-09-11
      • 2018-11-26
      相关资源
      最近更新 更多