Big-O characterization questions - java - java

Hi I was solving this problem, but I'm kind of stuck to choose which one is the right answer. So, I'm trying to get a help from you guys.
Here is the code:
for (int i=0; i < n; i++) { // loop1 from 0 to n-1
int total = 0;
for (int j=0; j < n; j++) // loop2 from 0 to n-1
for (int k=0; k <= j; k++) // loop3 from 0 to j
total += first[k];
if (second[i] == total) count++;
} return count;
From above code, loop1 and loop2 have n times n which has n^2 complex processing time
but the problem is loop3, I really don't want to say that has n times also since the limit of the loop is j not n.
In the worst time case, how should I conclude the complexity? will it going to be ((n+1)(n+2))/2 only for loop3? or ((n+1)(n+2))/2 for loop2 and loop3
My final answers are like this
first case: n * n * (((n+1)(n+2))/2) = O(n^4)
second case: n * (((n+1)(n+2))/2) = O(n^3)
which one will be the correct one? Or did I get both wrong?
p.s. please mind loop3 is 0 to j, not 0 to j-1

It is not clear from the question that what are the different cases you are concerned about. While discussing Big O, we only care about the most significant portion of complexity. Here j in the third loop can go up to n, as per the second loop. Hence there is no problem substituting it with n when calculating the total complexity. Since there are 3 loops in all, all directly or indirectly dependent on n, the complexity would be O(n^3). Also, you could ignore constants, so n-1 could be simply considered as n.
See
https://stackoverflow.com/a/487278/945214
Big-O for Eight Year Olds?

Related

What will be the time complexity of this algorithm

I am very new to competitive programming and to Big O notation.
public void function(int n){
for(int i = n; i > 0; i/=3){
for(int j = 0; j < i; j++){
System.out.println("Hello");
}
}
}
This is the algorithm.
As far as i know about time complexity.It defines how run time gets affected from number of inputs.
So here if we take a example
if 'n' is 10.
The outer loop runs log n times and the inner loop runs 'i' times.
the inner loop runs relatively to 'i' not 'n'.
So im a bit confused here as to how the time complexity is calculated.
I think it is O(log n).Please correct me if i am wrong.
Will it be O(log n) or O (n log n) or (n^2).
Please help me out with this.
Thank you.
I will try to explain it in the simplest term possible
The outer loop will simply run log(n) with base 3 times.
Since, i is decreasing by factor of 3 every time. The total work done is equal to :
n + n/3 + n/9 + n/27 + .... n/(3^log(n))
since, n/3 + ... + n/(3^log(n)) will always be less than n
for e.g. let n = 100
then, 100 + 100/3 + 100/9 + 100/27 + ... = 100 + (33.3 + 11.11 + 3.7 + ...)
we can clearly see the terms in the bracket will always be less than 100
The total time complexity of the overall solution will be O(n).
Actually it will never terminate cause i=0 and update is i *= 3 so i will stay 0 so we can say O(+oo)
assuming you meant for(int i =1... instead, then its O(n):
Outer loop is clearly O(log_3 n) cause we keep multiplying by 3
Inner loop will get executed O(log_3 n) times with iteration count of (1 + 3 + 9 + 27 + ... + 3^log_3(n)) which is clearly a geometric progression, solving which gives us approx 3^log_3(n)) which according to log rules gives n so this loop takes O(n) for all iterations, so total complexity is O(n)
for your code :
for(int i = n; i > 0; i/=3){
for(int j = 0; j < i; j++){
System.out.println("Hello");
}
}
Inner loop variable j is dependent on outer loop variable i, so your inner loop will be the one which will decide the complexity for your algorithm.
since j will run 'n' times in first run, 'n/3' times in second run and so on.. therefore your total complexity can be calculated as
n + n/3 + n/9 + n/27 + .......
resulting in O(n)
So this is a great question! It's a tricky one that takes a little more thinking to analyse.
As correctly stated in some of the other answers, the outer loop:
for(int i = n; i > 0; i/=3)
Will run log(n) times. Specifically log_3(n) times but in big O notation we don't often worry about the base so log(n) will be fine.
Now the nested loop is a bit trickier:
for(int j = 0; j < i; j++){
On first glance you may think this is a simple log(n) loop but lets look a little further.
So on the first iteration this will run N times since the value of i will be n. Next iteration it will be run n/3 times. Then n/9, n/27, n/81 etc....
If we sum this series, it is clear to see it will total less than 2n.
Therefore we can conclude this algorithm has a complexity of O(n).
In your code snippet:
for (int i=0; i < n; i*=3) {
for (int j=0; j < i; j++) {
System.out.println("Hello");
}
}
The outer loop in i is O(log_3(n)), because each increment of the loop decreases the amount of ground needed for i to reach n by a factor of 3. This is logarithmic behavior (log_3 in this case). The inner loop in j simply iterates the same number of times as whatever the outer value of i might be, so we can just square the outer complexity, to arrive at:
O(log_3(n)^2)

How to calculate the complexity of an algorithm? [duplicate]

This question already has answers here:
How can I find the time complexity of an algorithm?
(10 answers)
Closed 4 years ago.
int sum = 0;
for (int n = N; n > 0; n /= 2)
for(int i = 0; i < n; i++)
sum++;
int sum = 0;
for (int i = 1 i < N; i *= 2)
for (int j = 0; j < i; j++)
sum++;
int sum = 0;
for (int i = 1 i < N; i *= 2)
for (int j = 0; j < N; j++)
sum++;
I have been suffering from this for a lot of time. I am still a second-year student but I still can't calculate the complexity of an algorithm. How can I calculate it? I feel very incompetent because I never seem to get it!
For example, is the complexity of a for loop always N? How to know? Can you recommend any resources I can read? Any videos?
Well your first and second example is same (in terms of time complexity). For them, time complexity is O(N). Why is it. Let us compute. For the first example, your inner loop runs for N times, then N/2 times, then N/4 and goes upto 1. So, the time complexity is O(N+N/2+N/4+..+1) and sum of this GP is (2n-1). So, the time complexity for first case is O(N).
For the second example, your inner loop runs for 1 time, then 2 times, 4 times, and goes upto N. So, the time complexity is O(1+2+4+...+N) and sum of this GP is 2log(N+1)-1 which is equal to N. So, the time complexity for the second case is also O(N).
For the third example, first loop runs for log(N) time and inner loop runs for N time and since each of them is independent, required time complexity is O(NlogN). (All calculations are approximate and all log bases are 2)
Well, to know about time complexity of a for loop, you have to see how many times "i" is assigned a value (can be same or different).
To learn about time complexity, check out hackerearth material and every time you write an algorithm, try to calculate its time complexity. Its the best method to learn it and check out Masters theorem for recurrence relation but know its basic too.
Resource
https://www.geeksforgeeks.org/analysis-of-algorithms-set-4-analysis-of-loops/
Explanation
A general idea, Complexity of a loop means the number of times that will run. So a for loop for(int i=0;i<10;i++) is of Complexity O(n) where n=10. If there are multiple loops (not nested) the complexity of the code will be the highest n. If the loops are nested, like in the 3rd example you have shown above, the limit of both loop, which is N, gets multiplied. Making the complexity O(N square). (This is a general idea and not the precise definition!)
This previous question may be helpful because there are a few different approaches to calculate the complexity of an algorithm, and quite a few good resources.
As for your example, the complexity of a for loop may not always be N.
For example the following code snippet is linear (with a time complexity of N) because it goes from every iteration i = 0 to i = N sequentially,
for (int i = 0; i < N; i++) {
sum++;
}
Whereas this code snippet is logarithmic in its time complexity because it doesn't progress sequentially through every value from 0 to N, but instead is multiplied by 2.
for (int i = 0; i < N; i*2) {
sum++;
}

How many array accesses for the following

I have the following question.
Give the Tilde Approximation for the number of Array accesses for the following code
for (int i=0; i < n; ++i)
for (int j = i/2; j < i; ++j)
A[i] = B[j] + C[j];
However, I cannot figure out exactly how many array accesses there are, in terms of N
And i thought the answer would n^3 -- n for A, and n^2 for both B and C.
Do i seem to be on the right tack?
The N order is N^2 for big O notation.
This is due to 2 nested for loops.
If we assume that there is no compiler/jir optimizations, we have:
1) all arrays have the same amount of accesses
2) second for is performed ~ i/2 times
3) total sum(i=0,i=n) i/2 = O(n^2) (The sum of the first n natural numbers)
No, you can't count like that
your array A[] is been access the same times as B[] and C[], the only difference is that A is access j times at i position.
and other thing, is not nˆ3, you can't do A times B, you should analyze the both for`s to count the complexity
so, first for execute ntimes, second for execute n/2 times
In this case you have O(nˆ2 / 4) or just O(nˆ2)

How to determine Big O performance by looking at for loops?

I have just begun learning about Big O Notation and honestly I don't think I have the hang of it, and I am not quite sure how to determine the O() performance by just looking at for loops. I have listed a few examples and then some of the answers that I think are correct! Please let me know if they are wrong and any explanations would be greatly appreciated!
for (int i = 0; i <1000; i++) {
count ++;
I believe this would be O(n), because nothing else is going on in the for loop except constant time printing. We iterate 'n' times, or in this case 1000?
for (int i = 0; i < n; i++) {
for(int j = 0; j < n; j++)
count ++;
Would this one have an O(n^2) because the loops are nested and it iterates n twice, n*n?
for (int i = 0; i < n; i++) {
for( int j = i; j < n; j++)
count++;
Is this one another O(n^2) but in the worst case? Or is this O(n log n)?
Big-O notation is supposed to be a guide to help the user understand how the runtime increases with input.
For the first example, the loop runs exactly 1000 times no matter what n is, thus it is O(1000) = O(1) time.
For the second example, the nested loop runs n times for every time the outer loop runs, which runs n times. This is a total of n*n = n^2 operations. Thus the number of operations increases proportional to the square of n, thus we say it is O(n^2).
For the third example, it is still O(n^2). This is because Big-O notation ignores constants in the exact formula of the time complexity. If you calculate the number of times j runs as i increases, you get this pattern.
i: 0 1 2 3 ...
j: n n-1 n-2 n-3 ...
In total, the number of operations is around 1/2 n^2. Since Big-O notation ignores constants this is still O(n^2)

Worst Case Big O with Java Algorithms

1.
for(i = 0; i < 3; i++){
for(j = 0; j < 10; j++){
print i+j;
}
}
I would assume Big O would be 30 since the most amount of times would be 3*10.
2.
for(i = 0; i < n; i++){
for(j = 0; j < m; j++){
print i+j;
}
}
Would be O be n*m?
3.
for(i = 0; i < n; i++){
for(j = 0; j < m; j++){
for(int k = 1; k < 1000; k *= 2){
print i+j+k;
}
}
}
n * m * log base 2 (1000) The Big O is in nlog(n) time
4.
for(i = 0; i < n - 10; i++){
for(j = 0; j < m/2; j++){
print i+j;
}
}
5.
for(i = 0; i < n; i++){
print i;
}
//n and m are some integers
for(j = 1; j < m; j *= 2){
print j;
}
Can someone give me a hand with this if you know Big O. I am looking at these and at a loss. I hope I am posting this in the right location, I find these problems difficult. I appreciate any help.
I think it's important just to point out that Big O notation is all about functions that, given an arbitrary constant, will be considered upper bounds at some point.
O(1)
This is because each loop iterates in a constant amount of time. We would refer to this as O(1) instead of O(30) because the function which is the upper bound is 1 with an arbitrary constant >=30.
O(n*m)
Simply because we have to loop through m iterations n times.
O(n*m)
This is the same as the previous one, only we're throwing in another loop in the middle. Now you can notice that this loop, similar to the first problem, is just a constant time. Therefore, you don't even need to really spend time figuring out how often it loops since it will always be constant - it is O(1) and would be interpreted as O(n*m*1) which we can simply call O(n*m)
O(n*m)
For the outer loop, don't get caught up on the .. - 10 and realize that we can just say that loop runs in O(n). We can ignore that .. - 10 for the same reason we ignored the exact values in the first problem; constants don't really matter. This same principle applies for the m/2 because you can think of m just being manipulated by a constant of 1/2. So we can just call this O(n*m).
T(n) = O(n) + O(lg m) => O(n + lg m)
So there are two components we have to look at here; the first loop and the second loop. The first loop is clearly O(n), so that's no problem. Now the second loop is a little tricky. Basically, you can notice that the iterator j is growing exponentially (notably power of 2's), therefore that loop will be running the inverse of exponentially (logarithmic). So this function runs in O(n + lg m).
Any constant factor can be ignored. O(30) is equal to O(1), which is what one would typically say for 1).
2) Just so.
3) in O(n*m*log_2(1000)), log_2(1000) is constant, so it's O(n*m).
4) O(n-10) is same as O(n). O(m/2) is same as O(m). Thus, O(n*m) again.
5) Trivially O(n).
6) O(log_2(m)).

Categories