数组迭代的复杂性不断降低

时间:2017-11-02 23:37:19

标签: arrays algorithm big-o

所以我有点不确定这个时间的复杂性究竟是什么(我认为它是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,但我真的可以称之为吗?感谢。

1 个答案:

答案 0 :(得分:1)

直观地说,我们应该期望它类似于Θ(n 2 / 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个术语的总共(n / k)+ 1个副本,所以我们可以将事情重新组合为

  

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) - n 2 / 2k 2 + n - n / 2k

     

= 2n 2 k / 2k 2 - n 2 / 2k 2 + n - n / 2k

     

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

     

= Θ(n 2 / k + n)

所以数学以我们的直觉检查。