让以下算法为:
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)
。
谢谢。
答案 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)
时间。