【问题标题】:Path sum in a Directed Acyclic Graph有向无环图中的路径和
【发布时间】:2017-11-14 23:51:01
【问题描述】:

给定一个有向无环图,确定是否有任何分支返回等于 22 的路径和。在下面的示例中,可以在 (7 + 8 + 3 + 4) 处找到这样的路径。这种算法的运行时间复杂度是多少?

      7  
     / \  
    8   6  
   / \ / \  
  2   3   8  
 /   /    \     
5   4      1  

这就是我想出的。

public boolean hasPathToSum(Node root, int sum)
{
    if (root == null) return false;
    if (root.value == sum && (root.left == null && root.right == null))
        return true;

    return hasPathToSum(root.left, sum - root.value) || hasPathToSum(root.right, sum - root.value);
}

关于提高复杂性有什么更好的建议吗?

【问题讨论】:

  • 数据结构看起来更像二叉树而不是图(节点有left & right 而不是边列表)。在这种情况下,复杂度为O(n),其中n 是树中的节点总数,因为您正在访问每个节点。
  • 如果它是一棵树,则可以在O(n) 中进行广度优先遍历。可以在O(n^2) 中遍历森林。
  • 并非如此,即使在这个简单的示例中,节点“3”也被访问了两次。
  • 哦,我没看到3 有两个父母。没错,它是 DAG,而不是二叉树。
  • 最坏的情况是一个图,其中深度 i 上的每个节点都连接到深度 i+1 上的每个节点。我认为这需要O(n^2) 广度优先遍历。

标签: java algorithm data-structures graph tree


【解决方案1】:

如果图中的所有值都是非负数,您可以使用 memoization 在 O((n + m) * sum) 中解决此问题。在您的情况下,总和是固定的并且等于 22,因此解决方案实际上是线性的。

记忆化是一种不会两次计算相同值的技术。请注意,hasPathToSum(root, sum) 是一个纯函数:其结果仅取决于参数,没有副作用。这意味着我们可以将这个函数的结果保存到某个映射 (root, sum) -> bool 中(可能是 Java 中的 HashMap 或 TreeMap,由于我不熟悉语言,我无法准确地说)。

现在,当调用函数时,我们检查它的参数是否出现在映射中。如果是,只需返回保存的值。否则计算它,保存到地图中并返回。这样,对于任何一组参数,该函数实际上只计算一次。

最后的优化只适用于非负值。请注意,如果 x hasPathToSum(v, x) 的结果为 false。因此您可以进行截断:如果是这种情况,请立即返回 false。这种优化确保对于每个节点,hasPathToSum 将被调用,最多有 23 个不同的总和值,产生上述运行时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 2016-09-25
    相关资源
    最近更新 更多