对于以下循环,有人可以帮我找到T(n),即内部循环作为n的函数运行的次数:
for (int i = 0; i < n; i++)
for (int j = i; j > 0; j /= 2)
cout << j << endl;
仅此一看,我就知道big-O是O(n*log(n))
,但我也应该弄清楚T(n)
我已经运行了代码,并找到了执行该语句的次数。我想出了一个系列,但还没有想出如何简化它:
log_2(n-1)+1+log_2(n-2)+1+log_2(n-3)+1+.......
我尝试使用对数乘积规则将其简化为
T(n)=log_2((n-1)!2^2))
但是不满足方程式。
*编辑以解释我的意思T(n)
答案 0 :(得分:2)
通过T(n)
,我认为您的意思是用于输入大小为n
的“基本操作”数量的函数。首先,您必须选择“基本操作”。在这种情况下,cout << j << endl
似乎是一个合理的选择。
让我们从一些更简单的示例开始:
for (int i = 0; i < n; i++)
cout << i << endl;
(由于我在这里不能使用sigma表示法,因此我将写sum(a, b, c)
,其中a
通常写在sigma之下,b
写在sigma之上,而{{1 }}写在sigma的右边。)
for循环的分析基于求和。我们每个输出操作执行一次,所以c
。我们可以通过数学归纳法证明T(n) = sum(i = 0, n - 1, 1)
。
由于这与您的外部for循环相同,因此我们可以编写T(n) = n
。
要分析内部循环,让我们首先注意是否计数相反:
T(n) = sum(i=0, n, THE NUMBER OF STEPS FOR THE INNER LOOP)
分析是一样的
现在让我们做一些更复杂的事情:
for (int i = n; i > 0; i--)
cout << i << endl;
我们需要使用sigma计数法来计算步数,因此我们将对代码进行几次转换,同时保留执行的步数。与前面的计数示例具有相同的步骤数相同,我们可以将其写为
for (int i = n; i > 0; i /= 2)
cout << i << endl;
我了解输出会有所不同,但我们只关心步骤数。
我们需要再进行一次转换,因为sigma表示法总是增加1:
for (int i = 0; i < n; i *= 2)
cout << i << endl;
现在,这很像我们的第一个示例:for (int i = 0; i < n/2; i++)
cout << i << endl;
。
所以现在我们可以将内部循环的总和添加到我们的函数中:
T(n) = sum(i=0, n/2 - 1, 1) = n/2
最后一步是为一个封闭的公式求和。留给读者练习。