这个算法会在O(n)中运行吗?

时间:2015-05-29 05:29:12

标签: algorithm big-o time-complexity complexity-theory asymptotic-complexity

注意:这是破解编码面试第5版的问题4.3

问题:给定排序(递增顺序)数组,编写算法以创建具有最小高度的二叉搜索树

这是我的算法,用Java编写来解决这个问题

  public static IntTreeNode createBST(int[] array) {
         return createBST(array, 0, array.length-1);
   }
   private static IntTreeNode createBST(int[] array, int left, int right) {
        if(right >= left) {
            int middle = array[(left + right)/2;
            IntTreeNode root = new IntTreeNode(middle);
            root.left = createBST(array, left, middle - 1);
           root.right = createBST(array, middle + 1, right);
            return root;
         } else {
             return null;
         }
    }

我对作者检查了这段代码并且它几乎相同。
但是我很难分析这个算法的时间复杂度。
我知道这个不会像Binary Search一样在 O(logn)中运行,因为你在每个递归级别都没有做同样多的工作。 E.G在第一级,1个工作单元,第2级 - 2个工作单元,第3级 - 4个工作单元,一直记录 2 (n)级 - n个工作单元。

因此,基于此算法,此算法所采用的步数将受此数学表达式的限制

enter image description here

在看了Infinite geometric series之后,我评估了 enter image description here

或2n将在 O(n)

你们同意我在这里的工作吗?这个算法会在 O(n)中运行,或者我错过了什么,或者它实际上是在 O(nlogn)中运行还是其他一些功能类?

2 个答案:

答案 0 :(得分:5)

有时,您可以通过计算结果中每个项目的时间量而不是求解递归关系来简化计算。这个技巧适用于此。首先将代码更改为明显等效的形式:

private static IntTreeNode createBST(int[] array, int left, int right) {
    int middle = array[(left + right)/2;
    IntTreeNode root = new IntTreeNode(middle);
    if (middle - 1 >= left) {
        root.left = createBST(array, left, middle - 1);
    }
    if (right >= middle + 1) {
        root.right = createBST(array, middle + 1, right);
    }
    return root;
}

现在每次调用createBST都会直接创建1个节点。由于最终树中存在“sn”节点,因此n总共必须createBST次调用,并且由于每次调用直接执行一定量的工作,因此总体时间复杂度为O(n)。

答案 1 :(得分:1)

如果您在递归时感到困惑,请将递归调用(当然是精神上的)替换为循环。例如,在上面的函数中,您可以将递归调用想象成在“while循环”中。因为,它现在是一个while循环执行,直到所有n个节点遍历为止,复杂度为O(n)。