Worst Case Big O with Java Algorithms - java

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)).

Related

How do you calculate T(n) in an equation from a code fragment?

I'm having trouble converting code fragments into equations that figure out T(n) of said equation. An example code fragment is this:
a = b + c;
d = a + e;
This specific questions asks to determine T(n). How would I go about doing that? Another example code given is as follows:
sum = 0;
for (i=0; i<3; i++)
for (j=0; j<n; j++)
sum++;
I've attempted to follow instruction and examples from other questions that are similar, but am getting stuck on how the equation is found exactly. Here's an example and result that I know of so far:
Code:
sum = 0;
i = 1;
while (i <= N)
{
sum = sum + 1;
i++;
}
With the result being this:
T(N) = 2 + (Σ with N on top and i+1 on bottom) * 2
and that ends up simplifying to 2+2N
I'm unsure of how this result is found though.
Here is how you can approach this problem:
sum = 0; // 1 - O(1)
for (i=0; i<3; i++) // This will run 3x times - O(3)
for (j=0; j<n; j++) // This will run n times (O(n)), meaning the sum will be increased n times
sum++;
Then you can write T(n)=1+3*(1+n+2n)≈1+3n. This means that the time complexity for this code is O(n).
Generally, when looking at the simple for loop, like the one here, you can determine its complexity by looking at the condition statement. For j<n the complexity will be O(n), and for i<3 the complexity will be O(3).

Not understanding big O notation O(∑ i=0 n−1 (∑ j=i+1 n (j−i)))=O(∑ i=0 n−1 2 (1+n−i)(n−i))=O(n^3)

Working on the following problem:
Given a string s, find the length of the longest substring without repeating characters.
I'm using this brute force solution:
public class Solution {
public int lengthOfLongestSubstring(String s) {
int n = s.length();
int res = 0;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
if (checkRepetition(s, i, j)) {
res = Math.max(res, j - i + 1);
}
}
}
return res;
}
private boolean checkRepetition(String s, int start, int end) {
int[] chars = new int[128];
for (int i = start; i <= end; i++) {
char c = s.charAt(i);
chars[c]++;
if (chars[c] > 1) {
return false;
}
}
return true;
}
}
Tbe big O notation is as follows:
I understand that three nested iterations would result in a time complexity O(n^3).
I only see two sigma operators being used on the start of the formula, could someone enlighten me on where the third iteration comes to play in the beginning of the formula?
The first sum from i=0 to n-1 corresponds to the outer for loop of lengthOfLongestSubstring, which you can see iterates from i=0 to n-1.
The second sum from j = i+1 to n corresponds to the second for loop (you could be starting j at i+1 rather than i as there's no need to check length 0 sub-strings).
Generally, we would expect this particular double for loop structure to produce O(n^2) algorithms and a third for loop (from k=j+1 to n) to lead to O(n^3) ones. However, this general rule (k for loops iterating through all k-tuples of indices producing O(n^k) algorithms) is only the case when the work done inside the innermost for loop is constant. This is because having k for loops structured in this way produces O(n^k) total iterations, but you need to multiply the total number of iterations by the work done in each iteration to get the overall complexity.
From this idea, we can see that the reason lengthOfLongestSubstring is O(n^3) is because the work done inside of the body of the second for loop is not constant, but rather is O(n). checkRepitition(s, i, j) iterates from i to j, taking j-i time (hence the expression inside the second term of the sum). O(j-i) time is O(n) time in the worst case because i could be as low as 0, j as high as n, and of course O(n-0) = O(n) (it's not too hard to show that checkRepitions is O(n) in the average case as well).
As mentioned by a commenter, having a linear operation inside the body of your second for loop has the same practical effect in terms of complexity as having a third for loop, which would probably be easier to see as being O(n^3) (you could even imagine the function definition for checkRepitition, including its for loop, being pasted into lengthOfLongestSubstring in place to see the same result). But the basic idea is that doing O(n) work for each of the O(n^2) iterations of the 2 for loops means the total complexity is O(n)*O(n^2) = O(n^3).

Big-O characterization questions - 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?

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)

What's the big-O of this code?

Could somebody please help me find the big-O of this code? I've already tried to calculate it but I just don't understand how.
int n = //user input
for (int i = 0; i < n; i++){
for (int j = 1; j < n; j = j * 2){
System.out.println(i * j);
}
}
You should ask yourself how many iterations are in the outer loop and how many iterations are in the inner loop. Then you multiply the two.
The outer loop is simple - i grows from 0 to n-1 in increments of 1, so the total number of iterations is n, which is O(n).
In the inner loop j grows from 1 to n-1, but j is multiplied by 2 in each iteration. If n=2^k, for some integer k, there would be k iterations, and log n = k. Therefore there are O(log n) iterations in the inner loop.
Multiplying the two, you get O(n)*O(log(n)) = O(n log(n));
O(n Log n). Why?
for(int i=0; i<n;i++){ // n
for(int j=1; j<n; j=j*2){ //Log n (multiplying by 2)
System.out.println(i*j);
}
}`
Using Sigma notation, you may do the following:

Categories