【问题标题】:Complexity of array sum with divide and conquer具有分治法的数组和的复杂性
【发布时间】:2018-07-11 22:41:42
【问题描述】:

设以下算法为:

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)

谢谢。

【问题讨论】:

  • The problem always gets divided in two new problems so that would be O(log n) -没有。每次划分时,您都不会丢弃任何一半。如果你像二分搜索一样丢弃任何一半,那么它是 O(logn) 否则你将计算递归树的所有叶子,它的顺序是 O(n)。

标签: algorithm time-complexity


【解决方案1】:

从高级的角度来看,您的算法就像在遍历平衡二叉树一样,其中每个节点都覆盖一个特定的区间[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) 时间。

【讨论】:

    【解决方案2】:

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

    我猜你指的是二分搜索算法,但因为我们知道搜索键将在除法的另一侧,所以每个除法的每一半都被跳过。

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

    O(n) 是正确的复杂度

    【讨论】:

      猜你喜欢
      • 2019-10-05
      • 2013-10-12
      • 2023-03-03
      • 2015-04-24
      • 1970-01-01
      • 2016-02-06
      • 2021-02-08
      • 2012-03-10
      • 2014-12-08
      相关资源
      最近更新 更多