【问题标题】:Complexity for array iteration that is constantly reduced不断降低的数组​​迭代的复杂性
【发布时间】:2018-04-15 15:00:56
【问题描述】:

所以我有点不确定这个时间复杂度到底应该叫什么(我认为是O(N^2),但我不确定我是否可以这样称呼它)

void solve(int[] nums, int k){
 int len = nums.length; 
  while(len > 0){ 
   for(int i = 0; i < len; i++){ System.out.println("hello"); }
   len-=k;
  }
}

所以我意识到它是:n + n-k + n-2k + n-3k + ... 我知道我不会在每次迭代中将搜索空间减半,因此显然不是 n*log(n) 其中 n 是数组的大小。我确实意识到它类似于发散系列(1+2+3+4+...);,因此,我之前的假设是O(N^2) == n(n+1)/2,但我真的可以这样称呼它吗?谢谢。

【问题讨论】:

  • 哇,这让我意识到它是 O(n*n/k),它只是 O(n^2/k),其中 k 是一些常数。谢谢。
  • 注意,如果k和你函数的参数一样,那么k不是常量,而是变量。您的复杂性分析必须依赖于 n(即 nums 的长度)和 k
  • len &lt;= 0 可能应该是len &gt; 0。并且乘以一个常数不会改变 big-O 复杂度,所以 O(k*f(n)) = O(f(n)) - 但这仅当 k 实际上是一个常数,而不是输入。

标签: arrays algorithm big-o


【解决方案1】:

直观地说,我们应该期望这类似于 Θ(n2 / k + n)。如果您将每个工作单元想象成一个正方形,您可以想象我们正在用这些正方形构建一个三角形。每列代表外循环的一次迭代。三角形的高度是 n,三角形的宽度是 (n / k),所以我们希望会出现这样的结果。例如,如果 k = 1 且 n = 5,则三角形如下所示:

*
**
***
****
*****

如果 k = 2 且 n = 6,则三角形如下所示:

*
*
**
**
***
***

其中的 n 项是必要的,因为如果我们允许 k 变得非常非常大,我们仍然总是至少进行一次循环迭代,因此我们不希望我们的运行时间降为零。

现在,让我们看看数学是否与我们一致。正如您所提到的,您正在查看总和

n + (n - k) + (n - 2k) + (n - 3k) + ... + (n - (n/k)k)。

这里一共有(n / k) + 1个n term的副本,所以我们可以重新组合为

n((n / k) + 1) - (k + 2k + 3k + ... + (n/k)k)。

然后我们可以分解出一个 k 项来得到

n((n / k) + 1) - k(1 + 2 + 3 + ... + (n / k))。

第二项是高斯著名的和停止在 (n / k) 处,结果为

n((n / k) + 1) - (n / k)((n / k) + 1) / 2.

分解出 ((n / k) + 1) 项得到我们

((n / k) + 1)(n - n / 2k)

如果我们现在将所有内容相乘,我们得到

n(n / k) - n2 / 2k2 + n - n / 2k

= 2n2k / 2k2 - n2 / 2k2 + n - n / 2k

= (2n2k - n2) / (2k2) + n - n / 2k

= Θ(n2 / k + n).

因此,我们凭直觉进行数学运算。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-07
    • 2021-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多