Code 1
int i = 0;
int j = 0;
while(i < n){
while(j < n){
printf("{%d,%d}",arr[i],arr[j]);
j++;
}
i++;
j = 0;
printf("\n");
}
Code 2
int result = 0;
int i = 0;
while (i < n / 2){
result += arr[i];
i += 1;
while (i >= n / 2 && i < n){
result += arr[i];
i += 1;
}
}
printf("%d\n", result);
I only know how to find time complexity with for loops, but I am uncertain about while loop.
It would be greatly appreciated if someone could help me find the total running time of each code.
A for loop, at the end of the day, IS a while loop. Something of the form:
for(int i=0; i<n; i++)
is equivalent to:
int i=0;
while(i<n)
{
i++;
}
In fact in pure mathematical analysis of algorithms you are supposed to make any for loop into a while loop in your algorithms (there are a couple reasons why).
Going back to your code. The analysis is simple:
Before the first iteration of the while loop the value of i is 0.
There exists a unique statement that updates the variable i (i++).
On every iteration of the outer loop i increases by 1.
The outer loop runs at most n times.
Before the iteration of any loop the value of j is 0.
There are 2 statements that update j (j=0 and j++)
Informally: we can tell before any iteration of the inner loop the value of j is 0.
Inside the inner loop the only statement that updates j is j++.
on every iteration of the inner loop j increases by 1.
The inner loop runs at most n times by the loop guard.
The outer loop runs at most n times, the inner loop runs at most n times for every iteration of the outer loop. All other statements are constant. The algorithm is in O(n*n)=O(n^2)
The second one is slightly more convoluted but:
Before the first iteration of the outer loop the value of i is 0.
Informally: the outer loop will run until the value of i is (n/2 - 1)
The update statement (i += 1) updates i to (n/2)
Informally: the inner loop runs (n-n/2 = n/2) times and it runs exactly once.
-The outer loop runs n/2 times, the inner loop runs n/2 times exactly once.
The algorithm thus runs O(n/2+n/2) = O(n) times
The first code sample is pretty much a classis for loop. Its complexity is O(n^2). This is because the inner loop has a complexity O(n) and it is run n times.
The second one is a bit more difficult, untill you see that is equivalent to a non nested loop (ignoring the complexity of the checks)
int result = 0;
int i = 0;
while (i < n){
result += arr[i];
i += 1;
}
printf("%d\n", result);
meaning its complexity is O(n)
The best approach to calculating time complexity is trying to actually understand how the algorithm works and counting the operations. In the second example, the inner loop never runs untill the outer loop is at its last iteration. And since they even execute the same code, the whole thing can be reduced to one loop.
Another good example is this:
for(i=0;i<n;i++){
for(j=i;j<n;i++){
//do something
}
}
Let's count the operations: 1 + 2 + 3 + 4 + ... + n. This comes down to n*n/2 leading to O(n^2)
Related
I'm having a bit of trouble figuring out the Big O run time for the two set of code samples where the iterations depend on outside loops. I have a basic understanding of the Big O run times and I can figure out the run times for simpler code samples. I'm not too sure how some lines are affecting the run time.
I would consider this first one O(n^2). However, I'm not certain.
for(i = 1; i < n; i++){
for(j = 1000/i; j > 0; j--){ <--Not sure if this is still O(n)
arr[j]++; /* THIS LINE */
}
}
I'm a bit more lost with this one. O(n^3) possibly O(n^2)?
for(i = 0; i < n; i++){
for(j = i; j < n; j++){
while( j<n ){
arr[i] += arr[j]; /* THIS LINE */
j++;
}
}
}
I found this post and I applied this to the first code sample but I'm still unsure about the second. What is the Big-O of a nested loop, where number of iterations in the inner loop is determined by the current iteration of the outer loop?
Regarding the first one. It is not O(n^2)!!! For the sake of simplicity and readability, let's rewrite it in the form of pseudocode:
for i in [1, 2, ... n]: # outer loop
for j in [1, 2, ... 1000/i]: # inner loop
do domething with time complexity O(1). # constant-time operation
Now, the number of constant-time operations within the inner loop (which depends on parameter i of the outer loop) can be expressed as:
Now, we can calculate the number of constant-time operations overall:
Here, N(n) is a harmonic number (see wikipedia), and there is a very interesting property of these numbers:
Where C is Euler–Mascheroni constant. Therefore, the complexity of the first algorithm is:
Regarding the second one. It seems like either the code contains a mistake, or it is a trick test question. The code resolves to
for (i = 1; i < n; i++)
for(j = i; j < n; j++){
arr[j]++;
j++;
}
The inner loop takes
operations, so we can calculate overall complexity:
For the second loop (which it appears that you still need an answer for), you have sort of a misleading bit of code, where you have 3 nested loops, so at first glance, it makes sense that the runtime is O(n^3).
However, this is incorrect. This is because the innermost while loop modifies j, the same variable that the for loop modifies. This code is actually equivalent to this bit of code below:
for(i = 0; i < n; i++){
for(j = i; j < n; j++){
arr[i] += arr[j]; /* THIS LINE */
j++;
}
}
This is because the while loop on the inside will run, incrementing j until j == n, then it breaks out. At that point, the inner for loop will increment j again and compare it to n, where it will find that j >= n, and exit. You should be familiar with this case already, and recognize it as O(n^2).
Just a note, the second bit of code is not safe (technically), as j may overflow when you increment it an additional time after the while loop finishes running. This would cause the for loop to run forever. However, this will only occur when n = int_max().
I need to write code that sorts in 'n' run time and I don't know how to calculate it. I need to simply sort an array so that left side is odd and right side is even. This is what I wrote and I wonder how do I to find the run time.
for (i=0;i<size-1;i++)
{
if(ptr[i]%2==0 || ptr[i]==0)
{
for (j=i;j<size;j++)
{
if(ptr[j]%2!=0)
{
temp=ptr[i];
ptr[i]=ptr[j];
ptr[j]=temp;
break;
}
}
}
}
Thanks in advance.
Your runtime for this Code is O(N^2)
You can use Counting Sort to sort an array in linear time
For reference Counting Sort
As #VenuKant Sahu answered, OP's code is O(n*n)
That is due to its double nested for loops
for (i=0;i<size-1;i++)
...
for (j=i;j<size;j++)
...
I need to write code that sorts in 'n' run time
O(n) algorithm (did not want to just give the code)
The number of loop iterations below can not exceed n/2.
The increment even_side happens at most n times.
The decrement odd_side happens at most n times.
// set up indexes
int even_side = left-most valid index
int odd_side = right-most valid index
loop {
while (the_even_index_is_not_at_the_right_end && is_even(a[even_side]) increment even_side;
while (the_odd_index_is_not_at_the_left_end && !is_even(a[odd_side]) decrement odd_side
compare the indexes
if (done) exit the loop;
a[even_side] <==> a[odd_side]
}
Some helper code to set up a random array.
#define N 10
srand(time(NULL));
int a[N];
for (int i = 0; i<N; i++) {
a[i] = rand()%100;
printf(" %d", a[i]);
}
puts("");
I have been tasked with optimizing a particular for loop in C. Here is the loop:
#define ARRAY_SIZE 10000
#define N_TIMES 600000
for (i = 0; i < N_TIMES; i++)
{
int j;
for (j = 0; j < ARRAY_SIZE; j++)
{
sum += array[j];
}
}
I'm supposed to use loop unrolling, loop splitting, and pointers in order to speed it up, but every time I try to implement something, the program doesn't return. Here's what I've tried so far:
for (i = 0; i < N_TIMES; i++)
{
int j,k;
for (j = 0; j < ARRAY_SIZE; j++)
{
for (k = 0; k < 100; k += 2)
{
sum += array[k];
sum += array[k + 1];
}
}
}
I don't understand why the program doesn't even return now. Any help would be appreciated.
That second piece of code is both inefficient and wrong, since it adds values more than the original code.
The loop unrolling (or lessening in this case since you probably don't want to unroll a ten-thousand-iteration loop) would be:
// Ensure ARRAY_SIZE is a multiple of two before trying this.
for (int i = 0; i < N_TIMES; i++)
for (int j = 0; j < ARRAY_SIZE; j += 2)
sum += array[j] + array[j+1];
But, to be honest, the days of dumb compilers has long since gone. You should generally leave this level of micro-optimisation up to your compiler, while you concentrate on the more high-level stuff like data structures, algorithms and human analysis.
That last one is rather important. Since you're adding the same array to an accumulated sum a constant number of times, you only really need the sum of the array once, then you can add that partial sum as many times as you want:
int temp = 0;
for (int i = 0; i < ARRAY_SIZE; i++)
temp += array[i];
sum += temp * N_TIMES;
It's still O(n) but with a much lower multiplier on the n (one rather than six hundred thousand). It may be that gcc's insane optimisation level of -O3 could work that out but I doubt it. The human brain can still outdo computers in a lot of areas.
For now, anyway :-)
There is nothing wrong on your program... it will return. It is only going to take 50 times more than the first one...
On the first you had 2 fors: 600.000 * 10.000 = 6.000.000.000 iterations.
On the second you have 3 fors: 600.000 * 10.000 * 50 = 300.000.000.000 iterations...
Loop unrolling doesn't speed loops up, it slows them down. In olden times it gave you a speed bump by reducing the number of conditional evaluations. In modern times it slows you down by killing the cache.
There's no obvious use case for loop splitting here. To split a loop you're looking for two or more obvious groupings in the iterations. At a stretch you could multiply array[j] by i rather than doing the outer loop and claim you've split the inner from the outer, then discarded the outer as useless.
C array-indexing syntax is just defined as (a peculiar syntax for) pointer arithmetic. But I guess you'd want something like:
sum += *arrayPointer++;
In place of your use of j, with things initialised suitably. But I doubt you'll gain anything from it.
As per the comments, if this were real life then you'd just let the compiler figure this stuff out.
This is from an old midterm. I am looking over it trying to study for my final.
Fun(int n, int A[]){
for(i = 0;i < A.length; i += 2){
A[i] = n;
}
return;
}
It asks for the loop invariant, at the location just after the loop begins, before the assignment of A[i]. It also asks what the invariant and exit conditions imply about what the loop achieves when it exits.
I answered:
Loop invariant is i < A.length
Exit conditions are i >= A.length
This with i+=2 implies that the array A has entries equal to n on every even number n entry less than or equal to A.length
I was not awarded full credit, and think it may be due to the loop invariant. Can anyone clarify?
int i, j;
for(i=0; i<n*n; i++)
{
if(i % n == 0)
for(j=0; j<n; j++)
x++;
else
x--;
}
I'm new to runtime analysis so I'm just checking my answer on here to see if I have the right idea.
I have to find a tight runtime bound for that segment and give a reasoning.
I came up with O(n²).
My reasoning behind it is because it runs the first for loop n² times. It only runs the second for loop if i is divisible by n.
Is this okay or am I completely wrong in my analysis?
The outer loop runs n² times. Every n-th run (so n runs in total), it starts another loop, which runs n times. That amounts to n² + n * n which equals 2n² which is a runtime of O(n²).