繁体   English   中英

找到算法的 T(n)

[英]Finding the T(n) of An Algorithm

好的,所以当我的教授在课堂上复习时,它看起来很简单,但是当我做作业时,我变得糊涂了。 这是一个家庭作业的例子。

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。如果它不明显,我很困惑。 如果有人能告诉我如何解决它,那会让我开心。 谢谢你们。

让我们深入研究这个函数。 让我们选择一些数字。

说,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 to n)。

我们从预计算中知道:= (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)。

希望这可以帮助!

这并不难。

单循环的 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 - (i+1) n-1次(其中 i 从 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<n ,那是ni

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

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

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

在您的情况下,问题是:根据外循环变量的值,内循环进行了多少次迭代?

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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM