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