求一个算法的T(n)

时间:2015-09-03 22:25:02

标签: c++ algorithm big-o

好的,所以当我的教授在课堂上讨论时,它看起来很简单,但是当我完成作业时,我感到很困惑。这是一个功课的例子。

for (int i = 0; i < n; i++)    // I know this runs at T(n)
 for (int j = n - 1; j >= i; j--)
 cout << i << " " << j << endl; 

这是我理解的一个例子

for(int i=0; i<n-1; i++) {
  for(int j=i+1; j<n; j++) {
    1 Simple statement
   }

对于那个例子,我只插入0,1和2.对于0,它运行n-1,1为n-2和2 n-3。所以我认为,对于作业示例,如果我插入0,它将运行n + 1,因为j必须大于或等于i,即0.如果它不明显,我很漂亮困惑。如果有人能告诉我如何解决它,那就是我的一天。谢谢你们。

3 个答案:

答案 0 :(得分:0)

让我们深入了解功能。我们来挑选一些数字。

说,n = 5

所以我们的代码看起来像这样(神奇的伪代码使用INCLUSIVE循环,而不是它太重要了)

(1)for i = 0 to 4
  (2)for j = 4 to i
     (3)print i j
  next
next

所以这是一个偏好问题,但通常假设循环每次执行需要花费1个简单语句(比较和增量)。因此,我们假设语句(1)和(2)的成本为2.语句(3)的成本为1.

现在确定T(n)。

我们的外循环for i = 0 to 4正好运行n次。 我们的内循环for j = 4 to i。 。 。我们会在那里挖一分钟。

对于n = 5的示例,循环(2)将执行如此

j = 4; i = 0;  j = 4; i = 1;  j = 4; i = 2;  j = 4; i = 3  j = 4; i = 4;
j = 3; i = 0;  j = 3; i = 1;  j = 3; i = 2;  j = 3; i = 3;
j = 2; i = 0;  j = 2; i = 1;  j = 2; i = 2;
j = 1; i = 0;  j = 1; i = 1;
j = 0; i = 0; 

因此它形成了这种金字塔形状,每次我们减少1次迭代。这个特殊的例子运行了5 + 4 + 3 + 2 + 1 = 15次。

我们可以将其写为SUM(i; i = 0到n)。

我们从precalc得知:=(1/2)(n)(n + 1)。

并且(3)将执行与内循环完全相同的次数,因为它是唯一的语句。所以我们的总运行时间将是。 。 。 成本(1)+成本(2)+成本(3) (2)(n)+ 2(1/2)(n)(n + 1)+(1/2)(n)(n + 1)

我们可以清理它

(3/2)(n)(n + 1)+ 2n = T(n)。

也就是说,这假设循环成本为2,语句成本为1.通常说循环成本为0且语句成本为1更有意义。如果是这种情况,则T(n)=(1 / 2)(N)(N + 1)。

并且认为T(n),我们知道T(n)是O(n ^ 2)。

希望这有帮助!

答案 1 :(得分:0)

这并不难。

单循环的3个示例:

for (int i = 0; i < n; i++)
for(int i = 0; i < n-1; i++)
for(int i = 2; i < n-1; i++)

第一个循环执行内容n次(i=0,1,2,3,...,n-1) 同样,第二个循环只有n-1次 第三个是n-3因为它不是0,而是2 (如果n小于3,即n-3<0,则根本不会执行)

在像

这样的嵌套循环中
for(int i = 0; i < n-1; i++) {
  for(int j = 0; j < n; j++) {
    //something
  }
}  

对于外循环的每次传递,执行整个内循环,即。你可以将两个单循环计数相乘,以获得总共执行“某事”的频率。这是(n-1) * n = n^2 - n

如果内部循环依赖于外部循环的值,则会变得更复杂:

for(int i = 0; i < n-1; i++) {
  for(int j = i+1; j < n; j++) {
    //something
  }
}  

单独的内循环是n - (i+1)次,外循环n-1次(我从0变为n-2)。
虽然有“正确”的方法来计算这一点,但有点逻辑思维通常更容易,正如你已经做过的那样:

i-value => inner-loop-time
0 => n-1
1 => n-2
...
n-2 => n - (n-2+1) = 1  

所以你需要总和1+2+3+...+(n-1) 为了计算从1到x的和,以下公式有助于:

sum[1...x] = x*(x+1)/2  

因此,从1到n-1的总和是

sum[1...n-1] = (n-1)*(n-1+1)/2 = (n^2 - n)/2  

这就是上面循环的解决方案(你的第二个代码)。

关于第一个代码:
外循环:n
内循环:从n-1i包含,或从i到<=n-1的其他方式,
或者从i<nn-i

i >= innerloop
0 n
1 n-1
2 n-2
...
n-1 1

...而且从1到n的总和是(n^2 + n)/2

答案 2 :(得分:-3)

调查问题的一种简单方法是对其进行建模并查看结果数据。

在你的情况下,问题是:内循环的迭代次数取决于外循环变量的值?

let n = 10 in [0..n-1] |> List.map (fun x -> x,n-1-x);;

上面的1行是显示发生情况的模型。如果您现在查看结果输出,您会很快注意到某些内容......

  

val it:(int * int)list =     [(0,9); (1,8); (2,7); (3,6); (4,5); (5,4); (6,3); (7,2); (8,1);      (9,0)]

你注意到了什么?对于给定的N,你运行外循环N次 - 这是微不足道的。现在我们需要总结第二个数字,我们有解决方案:

sum(N-1..0) = sum(N-1..1) = N * (N-1) / 2

因此cout次来电的总数是N *(N-1)/ 2。

另一种实现相同目的的简单方法是稍微修改一下你的功能:

int count(int n) {
   int c = 0;
   <outer for loop>
       <inner for loop>
           c++;
   return c;
}