Time complexity of this function - c

I am pretty sure about my answer but today had a discussion with my friend who said I was wrong.
I think the complexity of this function is O(n^2) in average and worst case and O(n) in best case. Right?
Now what happens when k is not length of array? k is the number of elements you want to sort (rather than the whole array).
Is it O(nk) in best and worst case and O(n) in best case?
Here is my code:
#include <stdio.h>
void bubblesort(int *arr, int k)
{
// k is the number of item of array you want to sort
// e.g. arr[] = { 4,15,7,1,19} with k as 3 will give
// {4,7,15,1,19} , only first k elements are sorted
int i=k, j=0;
char test=1;
while (i && test)
{
test = 0;
--i;
for (j=0 ; j<i; ++j)
{
if ((arr[j]) > (arr[j+1]))
{
// swap
int temp = arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
test=1;
}
} // end for loop
} // end while loop
}
int main()
{
int i =0;
int arr[] = { 89,11,15,13,12,10,55};
int n = sizeof(arr)/sizeof(arr[0]);
bubblesort(arr,n-3);
for (i=0;i<n;i++)
{
printf("%d ",arr[i]);
}
return 0;
}
P.S. This is not homework, just looks like one. The function we were discussing is very similar to Bubble sort. In any case, I have added homework tag.
Please help me confirm if I was right or not. Thank you for your help.

Complexity is normally given as a function over n (or N), like O(n), O(n*n), ...
Regarding your code the complexity is as you stated. It is O(n) in best case and O(n*n) in worst case.
What might have lead to misunderstanding in your case is that you have a variable n (length of array) and a variable k (length of part in array to sort). Of course the complexity of your sort does not depend on the length of the array but on the length of the part that you want to sort. So with respect to your variables the complexity is O(k) or O(k*k). But since normally complexity notation is over n you would say O(n) or O(n*n) where n is the length of the part to sort.

Is it O(nk) in best and worst case and O(n) in best case?
No, it's O(k^2) worst case and O(k) best case. Sorting the first k elements of an array of size n is exactly the same as sorting an array of k elements.

That's O(n^2), the outer while goes from k down to 1 (possibly stopping earlier for specific data, but we're talking worst case here), and the inner for goes from 0 to i (which in turn goes up to k), so multiplied they're k^2 in the worst case.
If you care about the best case, that's O(n) because the outer while loop only executes once then gets aborted.

Related

Best/worst case of finding minimum element in an array

I am trying to find the minimum element in an array, and I've been asked to figure out the number of comparisons needed while using the naïve approach. So the code I've written is:
int findMin(int arr[], int size) {
int comparisons = 0;
int temp = arr[0];
for (int i = 1; i < size; i++) {
comparisons++;
if (arr[i] < temp) {
temp = arr[i];
}
}
return comparisons;
}
Doesn't this require n-1 comparisons in all cases? Because I'll have to check all elements from arr[1] to arr[arr_length-1], and best case/worst case doesn't come into play as I don't know if the element is minimum unless I encounter all the elements of the array atleast once. Thus, it always does n-1 comparisons to get to the minimum element right?
One of my friends says its going to be 2(n-2)+1 worst case and n-1 best case but I don't know how that is? Am I wrong or is something else going on here?
With the unsorted array, since it don't have any information about the order of the unseen element, it have to look at them all, hence the time complexity is n-1.
Your algorithm requires n-1 comparisons in all cases, which means n-1 in the worst case and also n-1 in the best case. There are no optimal inputs or pessimal inputs of your function.
FYI: What is the best, worst and average case running times of an algorithm?

How to check Big O notation of a sorting algorithm?

I don't know how to solve it's complexity and such. How to know if it is faster than other sorting algorithms?
I find difficulty finding it because I'm a little bit bad at math.
#include <stdio.h>
int func(int arr[])
{
int temp;
int numofarrays=9999;
for(int runtime=1; runtime<=numofarrays/2; runtime++)
{
for(int i=0; i<=numofarrays; i++)
{
if(arr[i] > arr[i+1])
{
temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
if(arr[numofarrays-i-1] > arr[numofarrays-i])
{
temp=arr[numofarrays-i-1];
arr[numofarrays-i-1]=arr[numofarrays-i];
arr[numofarrays-i]=temp;
}
}
}
for(int i=0; i<=9999; i++)
{
printf("%i\n",arr[i]);
}
}
int main()
{
int arr[10000];
for(int i=0; i<=9999; i++)
{
arr[i]=rand() % 10;
}
func(arr);
}
The big o notation is where the limit of steps of the code you write goes to infinity. Since the limit goes to infinity, we neglect the coefficients and look at the largest term.
for(int runtime=1; runtime<=numofarrays/2; runtime++)
{
for(int i=0; i<=numofarrays; i++)
{
Here, the largest term of the first loop is n, and the largest term of the second is n. But since loop 2 makes n turns for each turn of the first loop, we're multiplying n by n.
Result is O(n^2).
Here:
for(int runtime=1; runtime<=numofarrays/2; runtime++)
{
for(int i=0; i<=numofarrays; i++)
{
you have two nested for loops that both depends of the array size. So the complexity is O(N^2).
Further you ask:
How to know if it is faster than other sorting algorithms?
Well big-O does not directly tell you about execution time. For some values of N an O(N) implementation may be slower than an O(N^2) implementation.
Big-O tells you how the execution time increases as N increase. So you know that an O(N^2) will be slower than an O(N) when N gets above a apecific value but you can't know what that value is! It could be 1, 5, 10, 100, 1000, ...
Example:
The empirical approach is to time (t) your algorithm for a given input of n. Then do that experiment for larger and large n, say, 2^n for n = 0 to 20. Plot (2^n, t) on a graph. If you get a straight line, it's a linear algorithm. If you get something that grows faster, try graph ln(t) and see if you get a line, that would be an exponential algorithm, etc.
The analytical approach looks scary and sometimes math heavy, but it's doesn't really have to be. You decide what your expensive operation is, then you count how of many of those you do. Anything that runs in loops including recursive functions are the main candidates the run-time of that goes up as the loop runs more times:
Let's say we want count the number of swaps.
The inner loop swap numofarrays times which is O(n).
The outer loop runs numofarrays/2 times which is also O(n) as we drop the factor 1/2 as it's doesn't matter when n gets large.
This mean we do O(n) * O(n) = O(n^2) number of swaps.
Your print loop, is not doing any swaps so we consider them "free", but if determine that they are as expensive as swaps then we want to count those too. Your algorithm does numofarrays print operations which is O(n).
O(n^2) + O(n) is just O(n^2) as the larger O(n^2) dominates O(n) for sufficiently large n.

Big O of duplicate check function

I would like to know exactly how to compute the big O of the second while when the number of repetitions keeps going down over time.
int duplicate_check(int a[], int n)
{
int i = n;
while (i > 0)
{
i--;
int j = i - 1;
while (j >= 0)
{
if (a[i] == a[j])
{
return 1;
}
j--;
}
}
return 0;
}
Still O(n^2) regardless of the smaller repetition.
The value you are computing is Sum of (n-k) for k = 0 to n.
This equates to (n^2 + n) / 2 which since O() ignores constants and minor terms is O(n^2).
Note you can solve this problem more efficiently by sorting the array O(nlogn) and then searching for two consecutive numbers that are the same O(n) so total O(nlogn)
Big O is an estimate/theoretical speed, it's not the exact calculation.
Like twain249 said, regardless, the time complexity is O(n^2)
BigO shows the worst case time complexity of an algorithm that means the maximum time an algorithm can take ever.It shows upper bound which indicates that whatever the input is time complexity will always be under that bound.
In your case the worst case will when i will iterate until 0 then complexity will be like:
for i=n j will run n-1 times for i=n-1 j will run n-2 times and so on.
adding all (n-1)+(n-2)+(n-3)+............(n-n)=(n-1)*(n)/2=n^2/2-n/2
after ignoring lower term that is n and constant that is 1/2 it becomes n^2.
So O(n^2) that's how it is computed.

Is the time complexity of this code correct?

Calculate the time complexity of this code fragment if the function "process" has a complexity of O(logn)
void funct (int a[], int n)
{
int i=0
while (i < n){
process (a, n);
if (a[i]%2 == 0)
i = i*2+1;
else
i = i+1;
}
I tried to calculate the best and worst case for time complexity;
Worst case is when the "else" statement get called so it should just be:
Worst case : T(n) = O(nlogn)
I have some problems with the best case. I tried this way but i don't know if this is correct
Since in the "if" statement "i" get incremented by "2i+1" it should be
i=2^k-1
2^k < n+1
so k < log_2(n+1)
Is correct to say that the while loop get executed (log_2(n+1)-2)/2 times because this is the last possible value for which i < n ?
if so the time complexity is O(lognlogn) in best case?
The best case is if the sampled values in a are all even. In that case, the complexity is O(log(n)*log(n)), since the loop trip count is O(log(n)).
The worst case is if the sampled values in a are all odd. In that case, the complexity is O(n*log(n)), since the loop trip count is O(n).

What is time complexity of this algorithm as Big-O notation?

This is a algorithm for this question: Rotate a array of n elements left by i positions. For instance, with n = 8 and i = 3, the array abcdefg is rotated to defghabc.
/* Alg 1: Rotate by reversal */
void reverse(int i, int j)
{ int t;
while (i < j) {
t = x[i]; x[i] = x[j]; x[j] = t;
i++;
j--;
}
}
void revrot(int rotdist, int n)
{ reverse(0, rotdist-1);
reverse(rotdist, n-1);
reverse(0, n-1);
}
What is the time complexity of this method? And is there any better solution to this problem?
Thanks indeed.
Should be roughly linear O(n).
The loop has to go for no more than (i+j)/2 times. Dropping the constant, O(i+j).
Big-O notation:
n is always O(n). (loops, as they have to go through several iterations)
1 so O(1). (if statement, specified quantity)
Agreed, it'd O(n) since we're merely shifting.
As a food for thought, another possible algorithm is to make a new array with the original appended to itself (ie. abcd --> abcdabcd). Then shift the pointers right n times! Of course, you'll need two pointers, one for the end, one for the beginning. Remember to cut off the end with '\0'
Same run time btw.

Resources