Complexity of Algorithm,when while loop changes - algorithm

This algorithm gets array as a input.
i=1
j=1
m=0
c=0
while i<=|A|
if A[i] == A[j]
c=c+1
j=j+1
if j>|A|
if c>m
m=c
c=0
i=i+1
j=i
return m
As i know, while loop's complexity is O(n). But I can't understand this algorithm and while loop. I need to know how does this algorithm's complexity calculate?

The while loop iterates on the i value, but it can perform several iterations with the same value. A secondary variable j is then incremented instead, and it runs up to the same maximum value.
This means that in fact this algorithm loops for every (unordered) combination of 2 values (i and j) from the given array A (including twice the same value). For example, if A is [1, 2, 3, 4], then i and j take these values per iteration of the while loop:
i | j
-----+-----
1 | 1
1 | 2
1 | 3
1 | 4
2 | 2
2 | 3
2 | 4
3 | 3
3 | 4
4 | 4
If we define n as the number of values in A, then the while loop iterates n(n+1)/2 times. In the example above: 4*5/2 = 10 times.
This is ½n²+½n = O(n²).
Note that the manipulation of the variables c and m in the code does not influence the time complexity, only the outcome of the function.

The slowest process decides the time taken in any process.
Understand this with an example;
I want to buy a car and a bicycle.
The price of a car is around $100000 and that of bicycle is $1000
When I add them I got this as $101000
A question arises here; What decides the cost of both?
Of course the car is the deciding factor. We would often ignore the price of bicycle in this case.
Time taken in a loop is more than that of declaring some variable or some arithmetic operation as this loop might run billion times.
i=1
j=1
m=0
c=0
This part will take one unit of time.
While, this entire code -->
while i<=|A|
if A[i] == A[j]
c=c+1
j=j+1
if j>|A|
if c>m
m=c
c=0
i=i+1
j=i
will run N number of times where N is length of your array.
Similarly those assignments and conditional operations will take O(1) time.
Adding them gives you
O(1) + O(N)= O(N) //{ Remember the addition of car and bicycle}

Related

How do I calculate the number of times each line of code is executed?

I have some pseudocode where I have to calculate the number of times the code is executed. The code is provided below.
Historgram1(A,B,N)
1 for k = 1 to N
2 B[k] = 0
3 for i = 1 to N
4 if A[i] == k
5 then B[k] = B[k] + 1
I know that line one would run n times but I am not sure about the others. I am also assuming that line 2 would run at least once since we are setting B[k] to a value of zero or would it be n + 1?
I am also unsure how to calculate th subsequent lines. Any help or guidance would be much appreciated.
Obviously, 1 and the whole loop body (2 to 5) are executed N times (for all values of k).
On every iteration of the outer loop, the inner loop (3) is executed N times (for all values of i), as is line 4; but line 5 is executed conditionally, only if A[i]==k.
So far we can say:
1, 2: N times
3, 4: N² times.
Now line 5 is executed every time some A[i] equals some k in [1, N]. This may occur at most N times (once per A[i]), but might never occur, that's all we can say without knowing more about A.
The global behavior of the algorithm is O(N²), due to lines 3 and 4.
Anyway, the function name hints that we are computing an histogram, so it is likely that most of the values are in range [1,k] (unless the choice of the bins is very poor). So we can conjecture that line 5 is executed close to N times, without exceeding it.
This program uses a very poor method to compute the histogram, as this can be done in time O(N).

CORMEN explanation of Insertion Sort Algorithm

I can't understand this particular use of the sigma(summation) notation in the explanation of the Insertion sort of the book Introduction to Algorithms by CLRS:
Let tj denote the number of times the while loop test in line 5 is executed for that value of j.
Can someone explain the use of sigma(summation) in Line 5,6,7?
I am aware of the summation formulas and uses.
I think I finally can clearly understand.
The Sigma is expressing that for each j, the while loop may run up to t times. So, when j is equal to 2, the while loop will run t times, when j is equal to 3, the while loop will run t times, but since we don't know if this t, when j=3, is equal to the previous t, when j = 2, we add a subscript to indicate that there are different t's.
The sum runs from 2 to n, and this already represent the for loop that is running in the outer layer.
So, in summary, the limits are from 2 to n, and each time we are in the for loop and we get to the while loop, this while loop will run t times.
Note - the sigma expressions should be j instead of t[j]. I'm not sure why the book used t[j] since it's using expressions of n for the other lines.
The sigma's are expressing the number of times that the corresponding line will be executed (worst case). For Sigma(j=2 to n) on line 5, that's a total count of 2+3+4+...+n = (n+2)(n-1)/2 = 1/2 n^2 + 1/2 n - 1. Note that for line 5, for j = 2, it's counting line 5 twice, once for i = 1 (the first compare of i > 0) and once for i = 0 (the second compare of i > 0).
Lines 6 and 7 depend A[i]> key, and worst case (A[i] always > key), loop one less than line 5, which explains the (tj - 1) factor => (2-1)+(3-1) + ... = 1+2+3+...+n-1 = (n)(n-1)/2.
This can be explained like:
[Outer loop] Line five will iterate 2 to n times (Let it is t times)
[Inside loop] Line six and seven will iterate same times from `2 to (t-1) times.

How to effectively calculate an algorithm's time complexity? [duplicate]

This question already has answers here:
Big O, how do you calculate/approximate it?
(24 answers)
Closed 5 years ago.
I'm studying algorithm's complexity and I'm still not able to determine the complexity of some algorithms ... Ok I'm able to figure out basic O(N) and O(N^2) loops but I'm having some difficult in routines like this one:
// What is time complexity of fun()?
int fun(int n)
{
int count = 0;
for (int i = n; i > 0; i /= 2)
for (int j = 0; j < i; j++)
count += 1;
return count;
}
Ok I know that some guys can calculate this with the eyes closed but I would love to to see a "step" by "step" how to if possible.
My first attempt to solve this would be to "simulate" an input and put the values in some sort of table, like below:
for n = 100
Step i
1 100
2 50
3 25
4 12
5 6
6 3
7 1
Ok at this point I'm assuming that this loop is O(logn), but unfortunately as I said no one solve this problem "step" by "step" so in the end I have no clue at all of what was done ....
In case of the inner loop I can build some sort of table like below:
for n = 100
Step i j
1 100 0..99
2 50 0..49
3 25 0..24
4 12 0..11
5 6 0..5
6 3 0..2
7 1 0..0
I can see that both loops are decreasing and I suppose a formula can be derived based on data above ...
Could someone clarify this problem? (The Answer is O(n))
Another simple way to probably look at it is:
Your outer loop initializes i (can be considered step/iterator) at n and divides i by 2 after every iteration. Hence, it executes the i/2 statement log2(n) times. So, a way to think about it is, your outer loop run log2(n) times. Whenever you divide a number by a base continuously till it reaches 0, you effectively do this division log number of times. Hence, outer loop is O(log-base-2 n)
Your inner loop iterates j (now the iterator or the step) from 0 to i every iteration of outer loop. i takes the maximum value of n, hence the longest run that your inner loop will have will be from 0 to n. Thus, it is O(n).
Now, your program runs like this:
Run 1: i = n, j = 0->n
Run 2: i = n/2, j = 0->n/2
Run 3: i = n/4, j = 0->n/4
.
.
.
Run x: i = n/(2^(x-1)), j = 0->[n/(2^(x-1))]
Now, runnning time always "multiplies" for nested loops, so
O(log-base-2 n)*O(n) gives O(n) for your entire code
Lets break this analysis up into a few steps.
First, start with the inner for loop. It is straightforward to see that this takes exactly i steps.
Next, think about which different values i will assume over the course of the algorithm. To start, consider the case where n is some power of 2. In this case, i starts at n, then n/2, then n/4, etc., until it reaches 1, and finally 0 and terminates. Because the inner loop takes i steps each time, then the total number of steps of fun(n) in this case is exactly n + n/2 + n/4 + ... + 1 = 2n - 1.
Lastly, convince yourself this generalizes to non-powers of 2. Given an input n, find smallest power of 2 greater than n and call it m. Clearly, n < m < 2n, so fun(n) takes less than 2m - 1 steps which is less than 4n - 1. Thus fun(n) is O(n).

Calculating time complexity of inner loops

So I am learning how to calculate time complexities of algorithms from Introduction to Algorithms by Cormen. The example given in the book is insertion sort:
1. for i from 2 to length[A]
2. value := A[i]
3. j := i-1
4. while j > 0 and A[j] > value
5. A[j+1] := A[j]
6. j := j-1
7. A[j+1] = value
Line 1. executes n times.
Line 4., according to the book, executes times.
So, as a general rule, is all inner loops' execution time represented by summation?
Anecdotally, most loops can be represented by summation. In general this isn't true, for example I could create the loop
for(int i = n; i > 1; i = ((i mod 2 == 0) ? i / 2 : 3 * i + 1)))
i.e. initialize i to n, on each iteration if i is even then divide it by two, else multiply i by three and add one, halt when i <= 1. What's the big-oh for this? Nobody knows.
Obviously I've never seen a real-life program using such a weird loop, but I have seen while loops that either increase and decrease the counter depending on some arbitrary condition that might change from iteration to iteration.
When the inner loop has a condition, the times the program will iterate through it(ti) will differ in each iteration of the outer loop. That's why it's equal to the summation of all the (ti)s.
However, if the inner loop was a for loop, the times the program will iterate through it is constant. So you just multiply the times of the outer loop by the times of the inner loop.
like this:
for i=1 to n
for j=1 to m
s++
the complexity here is n*m

Big O - for loop increment by partial N

void function(int N){
int c=0;
for (int i =0; i< N; i+= N/5)
c++;
}
What is the Big O of the above? Since for every N the loop would iterate 5 times, would it be O(1)?
Suppose for example that N = 100. Let's draw a table:
Iteration | i
----------+------
0 | 20
1 | 40
2 | 60
3 | 80
4 | 100
Note that it doesn't matter what value of N you pick, the number of iteration will be at most 5.
So we conclude that i doesn't depend on N.
So.. you're right, it's O(1).
Clarification
What's the difference between the above example and the loop: for(i=0;i<N;i+=20)?
If you draw the table, you'll get the same table! But, in this case, the result do depends on the value of N. If you pick N = 200 you'll get more than 5. So the result in this case will be O(N).
Since for every N the loop would iterate 5 times, would it be O(1)?
Precisely. The running time only depends on a constant – 5 – so it’s bounded by O(1).
Yes, the result is not depended upon N.
A formal to answer your question is like the following:

Resources