所以我一直试图使用以下算法找到大哦复杂性:
for (i = 1; i ≤ n;i + +)
for (j = 0; j < n; j = j + i)
print(Array[j]);
我被告知最佳方式是使用求和表示,我知道它可以用某种形式的系列表示,我真的不知道从哪里开始。我可以看到外部循环迭代n次,但内部循环是我得到的东西。我希望我能在这里推动正确的方向而不是答案。
答案 0 :(得分:1)
如果扩展两个for循环中的汇总数。数组索引应如下所示
(0,1,2,...... n-1),(0,2,4,... n-1),(0,3,6,9 ...... n-1) .....(0,N / 2),(0)
如果我们观察到第一个括号 n ,则第二个括号 n / 2 ,依此类推,直到最后一个括号 1 。
所以总和的总数可以写成
Summations = Sum(从i = 1到n)[n / i]
尝试求解求和,您将得到求和总数
答案 1 :(得分:0)
让我们按照你的建议使用求和,以获得更加分析/代数的方法。
首先,只考虑:
for (i = 1; i <= n; i++)
//some O(1) operation
这很简单,因为var i
获取从1到n的所有整数值范围。
我们可以用以下求和来表达这个循环:
现在,仅考虑:
for (j = 0; j < n; j = j + k)
//some O(1) operation
其中k是常数正整数项(如1,2,3,......等),k <= n
在这种情况下,var i
不获取从0到n-1的所有整数值范围。例如,让k=2
,然后我们可以在下图中表示正在发生的事情:
您在黑色中看到的是可能整数的间隔,红色代表var i
所需的实际整数值。如你所见,var i
在奇数上“跳”到n-1,所以在这种情况下(当k=2
时)只取偶数。
结果,当k=2
时,复杂性由求和给出:
通常,可以对任何k进行类似的方法。特别要注意的是,当k倾向于n时,复杂性往往会降低。
出于我们的目的,我们可以重写循环:
for (j = 0; j < n; j = j + k)
如:
for (j = 0; j < n/k-1; j++)
两者都具有相同的复杂性。
最后,请考虑:
for (i = 1; i <= n; i++)
for (j = 0; j < n; j = j + i)
//some O(1) operation
在内圈中,我们i
扮演的角色与k
之前相同。这意味着内部循环将以1到n范围内的i
的每个可能值执行。
重写为:
for (i = 1; i <= n; i++)
for (j = 0; j < n/k-1; j++)
//some O(1) operation
因此,复杂性由以下两个嵌套的总结给出:
首先,开始使用内部求和(右边的)进行评估:
注意我意外地将var名称从i
更改为x
,但这并不重要。
我们在这里得到了另一张海报给出的完全相同的结果。
现在,如果您只是展开最后一次求和,结果为:
现在括号中的是 n次谐波数,不要与谐波系列混淆。这是离散数学(和其他领域)中有趣的数字。
这可以表示为:
请注意,通过此分析,您可以获得渐近紧束缚。
BTW:您可以查看此link
中的最后一个等式语法为:
Sum[Sum[1, {j, 0, (n/i)-1}], {i, 1, n}]=Sum[n/x, {x, 1, n}]=n*Sum[1/x, {x, 1, n}]=n*(1+1/2+1/3+...+1/n)=n*HarmonicNumber[n]
我希望这会有所帮助。