打印从根到叶的所有节点的时间复杂度

时间:2015-03-26 06:12:04

标签: algorithm recursion time-complexity binary-tree depth-first-search

我使用DFS并递归编码此问题,如下所示:

/**
 * recursive
 */
public static List<List<Integer>> printAllPath(TreeNode root) {
    List<List<Integer>> rst = new ArrayList<List<Integer>>();

    helper(rst, new ArrayList<Integer>(), root);
    return rst;
}

public static void helper(List<List<Integer>> rst, ArrayList<Integer> list,
                   TreeNode root) {
    if (root == null) {
        return;
    }
    list.add(root.val);
    if (root.left == null && root.right == null) {
        rst.add(new ArrayList<Integer>(list));
    }
    helper(rst, list, root.left);
    helper(rst, list, root.right);
    list.remove(list.size() - 1);
}

在搜索互联网后,我发现此算法的平均时间复杂度为O(nlogn),最差的情况为O(n^2),这是正确的吗?为什么?有人可以解释一下吗?

我不太熟悉分析树的时间复杂度。在这个问题中,如果我使用Queue来实现,时间复杂度应该是O(n)对吗?因为我只是迭代整个树一次。

但是如何分析使用递归的树的时间复杂度。

2 个答案:

答案 0 :(得分:3)

您的代码显然会收集并返回从根节点到叶节点的所有路径。它通过使用DFS实现。在算法执行期间访问每个节点,并且不会多次访问它们。但是,您必须在找到路径时打印或存储路径。在您的计划中,您创建新的ArrayList并将其存储在变量rst中。路径数等于叶节点数l,路径长度等于树h的高度,因此总复杂度为O(n + hl)

lh的值不是独立的,因此我们来看两个有趣的案例。在平衡二叉树的情况下,平均有n/2个叶节点,高度为log2(n),这给出O(nlogn)。另一方面,当树在链表中退化时,只有一个叶子,并且该路径的长度为n,因此这种情况的复杂度为O(n)

  

但是如何分析使用树的时间复杂度   递归?

关于时间复杂度,只计算递归调用的数量。如果空间复杂性是个问题,请通过迭代替换递归。

另见:

答案 1 :(得分:0)

当构建根到叶路径时,树中的每个节点都被触摸一次,因此它的复杂度为O(N),其中N是树中节点的数量,如上所述。

但是当将根到叶的路径添加到结果列表中时 (在代码段中rst.add(new ArrayList<Integer>(list));),然后复制包含路径的整个数组。由于数组副本的复杂性与其长度呈线性关系,而表示根到叶路径的数组大致包含h个节点,其中h是树的高度,而不是整体O(N * h)复杂性。

例如,考虑完美的二叉树。它具有N / 2叶节点,因此每个N / 2长度为log N的{​​{1}}根路径路径。迭代这些路径 - 直接复制或打印 - 总共涉及log N * N / 2,相当于O(N * h)