简体   繁体   English

找到算法的 T(n)

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

Okay so when my professor was going over it in class it seemed quite simple, but when I got to my homework I became confused.好的,所以当我的教授在课堂上复习时,它看起来很简单,但是当我做作业时,我变得糊涂了。 This is a homework example.这是一个家庭作业的例子。

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; 

Here's an example I understand这是我理解的一个例子

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

For that example I just plugged in 0, 1, and 2. For 0, it ran for n-1, at 1 for n-2 and at 2 n-3.对于那个例子,我只是插入了 0、1 和 2。对于 0,它运行 n-1,1 运行 n-2 和 2 n-3。 So I think that for the homework example if I plugged in 0 it would run for n+1 since j has to be greater than or equal to i which is 0. If it's not obvious, i'm pretty confused.所以我认为对于作业示例,如果我插入 0,它将运行 n+1,因为 j 必须大于或等于 i,即 0。如果它不明显,我很困惑。 If anyone could show me how to solve it, that'd make my day.如果有人能告诉我如何解决它,那会让我开心。 Thanks guys.谢谢你们。

Let's dig into the functon.让我们深入研究这个函数。 Let's pick some numbers.让我们选择一些数字。

say, n = 5说,n = 5

So our code looks like this (magical pseudo-code uses INCLUSIVE loops, not that it's too important)所以我们的代码看起来像这样(神奇的伪代码使用了 INCLUSIVE 循环,并不是说它太重要了)

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

So this is a matter of preference, but usually loops are assumed to cost 1 simple statement per execution (comparison, and incrementation).所以这是一个偏好问题,但通常假设循环每次执行(比较和增量)花费 1 个简单语句。 So we'll assume that statements (1) and (2) have a cost of 2. Statement (3) has a cost of 1.所以我们假设语句 (1) 和 (2) 的成本为 2。语句 (3) 的成本为 1。

Now to determine T(n).现在确定T(n)。

Our outer loop for i = 0 to 4 runs exactly n times.我们for i = 0 to 4外循环正好运行了 n 次。 Our inner loop for j = 4 to i .我们的内部循环for j = 4 to i . . . . We'll dig in there for a minute.我们将在那里挖掘一分钟。

For our example with n = 5 loop (2) will execute like so对于我们的 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; 

So it makes this kind of pyramid shape, where we do 1 less iteration each time.所以它形成了这种金字塔形状,每次我们减少 1 次迭代。 This particular example ran 5 + 4 + 3 + 2 + 1 = 15 times.这个特定的例子运行了 5 + 4 + 3 + 2 + 1 = 15 次。

We can write this down as SUM(i; i = 0 to n).我们可以把它写成 SUM(i; i = 0 to n)。

Which we know from precalc: = (1/2)(n)(n+1).我们从预计算中知道:= (1/2)(n)(n+1)。

And (3) will execute the exact same number of times as that inner loop since it's the only statement.并且 (3) 将执行与该内部循环完全相同的次数,因为它是唯一的语句。 So our total runtime is going to be.所以我们的总运行时间将是。 . . . . COST(1) + COST(2) + COST(3) (2)(n) + 2(1/2)(n)(n+1) + (1/2)(n)(n+1)成本(1) + 成本(2) + 成本(3) (2)(n) + 2(1/2)(n)(n+1) + (1/2)(n)(n+1)

We can clean this up to be我们可以把它清理干净

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

That said, this assumes that loops cost 2 and the statement costs 1. It's usually more meaningful to say loops cost 0 and statements cost 1. If that were the case, T(n) = (1/2)(n)(n+1).也就是说,这假设循环成本为 2,语句成本为 1。说循环成本为 0,语句成本为 1 通常更有意义。如果是这种情况,T(n) = (1/2)(n)(n +1)。

And givent that T(n), we know T(n) is O(n^2).鉴于 T(n),我们知道 T(n) 是 O(n^2)。

Hope this helps!希望这可以帮助!

It's not that hard.这并不难。

3 examples for single loops:单循环的 3 个示例:

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

The first loop executs it's content n times ( i=0,1,2,3,...,n-1 ).第一个循环执行它的内容n次( i=0,1,2,3,...,n-1 )。
The same way, the second loop is just n-1 times.同理,第二个循环只是n-1次。
The third would be n-3 because it starts not at 0, but 2第三个是n-3因为它不是从 0 开始,而是从 2 开始
(and if n is less than 3, ie. n-3<0 , it won't execute at all) (如果n小于 3,即n-3<0 ,它根本不会执行)

In a nested loop like在嵌套循环中

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

For each pass of the outer loop, the whole inner loop is executed, ie.对于外循环的每次传递,执行整个内循环,即。 you can multiply both single loop counts to get how often "something" is executed in total.您可以将两个单循环计数相乘以获得“某事”的总执行频率。 Here, it is (n-1) * n = n^2 - n .在这里,它是(n-1) * n = n^2 - n

If the inner loop depends on the value of the outer loop, it gets a bit more complicated:如果内循环依赖于外循环的值,它会变得有点复杂:

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

The inner loop alone is n - (i+1) times, the outer one n-1 times (with i going from 0 to n-2 ).单独的内部循环是n - (i+1)次,外部循环是n - (i+1) n-1次(其中 i 从 0 到n-2 )。
While there are "proper" ways to calculate this, a bit logical thinking is often easier, as you did already:虽然有“适当”的方法来计算这个,但有点逻辑思维通常更容易,就像你已经做的那样:

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

So you´ll need the sum 1+2+3+...+(n-1) .所以你需要总和1+2+3+...+(n-1)
For calculating sums from 1 to x, following formula helps:为了计算从 1 到 x 的总和,以下公式有帮助:

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

So, the sum from 1 to n-1 is所以,从 1 到n-1的总和是

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

and that´s the solution for the loops above (your second code).这就是上述循环的解决方案(您的第二个代码)。

About the first code:关于第一个代码:
Outer loop: n外环: n
Inner loop: From n-1 down to i included, or the other way from i up to <=n-1 ,内循环:从n-1i包含,或者从 i 到<=n-1的另一种方式,
or from i up to <n , that´s ni times或者从i<n ,那是ni

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

...and the sum from 1 to n is (n^2 + n)/2 . ...从 1 到 n 的总和是(n^2 + n)/2

One easy way to investigate a problem is to model it and look at resulting data.调查问题的一种简单方法是对其进行建模并查看结果数据。

In your case, the question is: how many iterations does the inner loop depending on the the value of the outer loop variable?在您的情况下,问题是:根据外循环变量的值,内循环进行了多少次迭代?

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

The 1 line above is the model showing what happens.上面的 1 行是显示发生了什么的模型。 If you now look at the resulting output, you will quickly notice something...如果您现在查看结果输出,您会很快注意到一些事情......

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

What is it you notice?你注意到了什么? For a given N you run the outer loop N times - this is trivial.对于给定的 N,您运行外循环 N 次 - 这是微不足道的。 Now we need to sum up the second numbers and we have the solution:现在我们需要总结第二个数字,我们有解决方案:

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

So the total count of cout calls is N * (N-1) / 2.所以cout调用的总数是 N * (N-1) / 2。

Another easy way to achieve the same is to modify your function a bit:实现相同目标的另一种简单方法是稍微修改您的函数:

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