time complexity ( studying for exam) - time-complexity

I am currently studying to an examen in algorithms and I am trying to solve a question about time complexity in java, but can't really figure out how to do it. I am suppose to calculate the expected time complexity. N is a positive integer.
for (int i=0; i < N; i++)
for (int j=i+1; j < N; i++) {
int x=j+1; int h=N-1; int k;
while(x<h) {
k=(x+h)/2;
if (a[i]+a[j]+a[k] == 0) { cnt++; break;}
if (a[i]+a[j]+a[k] < 0) x=k+1;
else h=k-1;
}}
The first for loop should run N times and the second should run N-1. Since x is j+1 I guessed that x= N-2. I dont know how to think after that with the while loop or if I have done anything right. Would really appreciate help!

Create your time complexity function in parts.
for (int i=0; i < N; i++) //Takes linear O(n)
for (int j=i+1; j < N; i++) { //Takes linear O(n) and in computer science we can safely assume -1 is irrelevant at N-1 in big O notation
int x=j+1; int h=N-1; int k; // 3 x O(1)
while( x < h ) { // Worst case is when j equals i + 1 where i = 0 so x is at lowest 2 and h equals to N-1 so h depends on N. So again loop takes linear O(n) time.
k=(x+h)/2; // Takes O(1) time
if (a[i]+a[j]+a[k] == 0) { // Takes O(1) time and if this gives true we do break from the while loop
cnt++; // Takes O(1) time
break; // Takes O(1) time
}
if ( a[i]+a[j]+a[k] < 0 ) { // Takes O(1) time
x=k+1; // Takes O(1) time
} else {
h=k-1; // Takes O(1) time
}
}
}
}
So in summary T(N) equals to O(N^3) and Ω(N^2)
More specific T(N) = N * N-1 * N-2 + 10 and this last while loop in avarage takes O(N/2) time but still in computer science it is same as O(N).
We are only interested in worst and best cases.
To confuse even more big O notation actually
T(N)=O(g(N)) means this:
I hope this answer helps even little bit...

Related

Best time complexity of a single loop?

I have a really simple question, I have this loop:
for (int i=0; i<n; i++) {
"some O(n) stuff here)"
}
what will be the BEST time complexity of this algorithm?
O(n)? (for loop O(1) * O(n) stuff)
or
O(n^2)? (for loop O(n) * O(n) stuff inside the loop)
Will the for loop itself be considered as O(n) as normally, or will it be considered as O(1)
since it will only make only 1 loop for the BEST case scenario?
You are right, the best time complexity is O(N) (and even Θ(N)), if the best running time of "stuff" is constant (even zero).
Anyway, if "stuff" is known to be best case Ω(f(N)), then the best total time is Ω(N f(N)).
If your loop is doing O(n) stuff for n times then the time complexity will be O(n^2). May you call it worst case. The best case and average case will be based on your some O(n) stuff that is executed with every iteration of your loop.
Lets take a simple example of bubble sort algorithm:
for (int i = 0; i < n - 1; ++i) {
for (int j = 0; j < n - i - 1; ++j) {
if (a[j] > a[j + 1]) {
swap(&a[j], &a[j + 1]);
}
}
}
Time complexity this will always be O(n^2), whether array is sorted (irrespective of order - ascending or descending) or not.
But this can be optimised by observing that the nth pass finds the nth largest element and puts it into its final place. So, the inner loop can avoid looking at the last n − 1 items when running for the nth time:
for (int i = 0; i < n - 1; ++i) {
swapped = false;
for (int j = 0; j < n - i - 1; ++j) {
if (a[j] > a[j + 1]) {
swap(&a[j], &a[j + 1]);
swapped = true;
}
}
if (swapped == false) {
break;
}
}
Now the best case time complexity is O(n) i.e. when the array is sorted in ascending order (in context of above implementation). Average and worst case are still O(n^2).
So, to identify the best case time complexity of your algorithm you have to show us the implementation of some O(n) stuff and if not implementation then at least show the algorithm that you are trying to implement.
As you stated it, it's O(n^2).
'Cause You are doing n times a O(n) operation.

Time complexity of for loop with if/else

Would the following code be considered O(1) or O(n)? The for loop has constant complexity which runs 10 times but I'm not sure whether the if condition would be considered O(n) or O(1).
for (i = 0; i < 10; i++)
{
if (arr [i] == 1001)
{
return i;
}
}
The complexity would be O(1), because regardless of how much you increase the input the complexity of the algorithm remains constant. Namely, the operations performed inside that loop are considered to have constant time, hence O(1).
for (i = 0; i < 10; i++)
{
if (arr [i] == 1001)
{
return i;
}
}
On the other hand if your loop was:
for (i = 0; i < 10; i++)
{
f(n)
}
and the function f(n) had a complexity of O(n) then the complexity of the entire code snippet would be O(n) since 10 * N can be labeled as O(n).
For a more in depth explanation have a look at What is a plain English explanation of “Big O” notation?

Finding the time complexity of a recursive algorithm with a double for loop

I am trying to find the tightest upper bound for the following upper bound. However, I am not able to get the correct answer. The algorithm is as follows:
public staticintrecursiveloopy(int n){
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.println("Hello.");
}
} if(n <= 2) {
return 1;
} else if(n % 2 == 0) {
return(staticintrecursiveloopy(n+1));
} else{
return(staticintrecursiveloopy(n-2));
}
}
I tried to draw out the recursion tree for this. I know that for each run of the algorithm the time complexity will be O(n2) plus the time taken for each of the recursive calls. Also, the recursion tree will have n levels. I then calculated the total time taken for each level:
For the first level, the time taken will be n2. For the second level, since there are two recursive calls, the time taken will be 2n2. For the third level, the time taken will be 4n 2 and so on until n becomes <= 2.
Thus, the time complexity should be n2 * (1 + 2 + 4 + .... + 2n). 1 + 2 + 4 + .... + 2n is a geometric sequence and its sum is equal to 2n - 1.Thus, the total time complexity should be O(2nn2). However, the answer says O(n3). What am I doing wrong?
Consider the below fragment
for(int i = 0; i < n; i++) {
for(int j = 0; j < n; j++) {
System.out.println("Hello.");
}
}
This doesn't need any introduction and is O(n2)
Now consider the below fragment
if(n <= 2) {
return 1;
} else if(n % 2 == 0) {
return(staticintrecursiveloopy(n+1));
} else {
return(staticintrecursiveloopy(n-2));
}
How many times do you think this fragment will be executed?
If n%2 == 0 then the method staticintrecursiveloopy will be executed 1 extra time. Otherwise it goes about decresing it by 2, thus it'll be executed n/2 times (or (n+1)/2 if you include the other condition).
Thus the total number of times the method staticintrecursiveloopy will be executed is roughly n/2 which when expressed in terms of complexity becomes O(n).
And the method staticintrecursiveloopy calls a part with complexity O(n2) in each iteration, thus the total time complexity becomes
O(n) * O(n2) = O(n3).

Time complexity of 2 nested loops

I want to detect the time complexity for this block of code that consists of 2 nested loops:
function(x) {
for (var i = 4; i <= x; i++) {
for (var k = 0; k <= ((x * x) / 2); k++) {
// data processing
}
}
}
I guess the time complexity here is O(n^3), could you please correct me if I am wrong with a brief explanation?
the time complexity here is O(n^2). Loops like this where you increment the value of i and k by one have the complexity of O(n) and since there are two nested it is O(n^2). This complexity doesn't depend on X. If X is a smaller number the program will execute faster but still the complexity stays the same.

Nested loops with time complexity log(log n)

Can there be an algorithm with two loops (nested) such that the overall time complexity is O(log(log n))
This arised after solving the following :
for(i=N; i>0; i=i/2){
for(j=0; j<i; j++){
print "hello world"
}
}
The above code has time complexity of N. (Using concept of Geometric Progression). Can there exists similar loop with time complexity O(log(log n)) ?
For a loop to iterate O(log log n) times, where the loop index variable counts up to n, then the index variable has to grow like the inverse function of log log k where k is the number of iterations; i.e. it has to grow like 2^2^k, or some other base than 2.
One way to achieve this is by starting at 2 and repeatedly squaring until you reach n - if the index variable is (((2^2)^2)...^2) with k squarings, then this equals 2^2^k as required:
for(int i = 2; i < n; i = i*i) {
//...
}
This loop iterates O(log log n) times, as required. If you absolutely must do it with nested loops, we can trivially add an extra loop which iterates O(1) times, leaving the total number of iterations asymptotically the same:
for(int i = 2; i < n; i = i*i) {
for(int j = 0; j < 10; j++) {
// ...
}
}