具有分而治之的数组和的复杂度

时间:2018-07-11 22:41:43

标签: algorithm time-complexity

让以下算法为:

sum(v, i, j) {
    if i == j
        return v[i]
    else {
        k = (i + j) / 2
        return sum(v, i, k) + sum(v, k+1, j)
    }
}

该算法的时间复杂度为O(n),但是我如何用自然语言证明其复杂度呢?该问题总是分为两个新问题,所以应该是O(log n),但是其余的复杂性从何而来?

应用主定理会产生预期的结果O(n)

谢谢。

2 个答案:

答案 0 :(得分:0)

将问题分为两部分并不一定意味着复杂度为log(n)。

我猜您指的是二进制搜索算法,但由于我们知道搜索关键字将在除法的另一侧,因此每个除法都会跳过每一半。

仅通过查看sudo代码,即可对每个分区进行递归调用,并且不会跳过任何内容。为什么会是log(n)?

O(n)是正确的复杂度

答案 1 :(得分:0)

从高级的角度来看,您的算法就像遍历平衡的二叉树一样,每个节点覆盖一个特定的间隔[i, j]。他们的孩子将间隔分为2个大致相等的部分,即[i, (i+j)/2][(i+j)/2 + 1, j]

让我们假设它们在这种情况下相等。 (换句话说,为了证明起见,数组n的长度是2的幂)

通过以下方式进行思考。您的算法正在遍历此平衡二叉树的n叶。每一个都是从长度1的间隔开始的。树的n/2个节点是这n个叶子的父节点。那些n/2节点具有n/4个父节点。一直进行到到达树的根节点为止,该树覆盖了整个时间间隔。

考虑这棵树中有多少个节点。 n + (n/2) + (n/4) + (n/8) + ... + 2 + 1。由于我们最初假设n = 2^k,因此我们可以将该总和公式化为指数总和,其总和公式为well known。事实证明,该树中有2^(k+1) - 1 = 2 * (2^k) - 1 = 2n - 1个节点。因此,显然遍历该树的所有节点将花费O(n)时间。