Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trouble finding understanding why complexity of two nested loops is O(n)?

So in the following code, j executes n times when i = 0. As soon as i iterates once (i = 0,2,3....n), j never executes, as the condition of the if statement is true and n is added to j. i continues to iterate until n which is when the loop (both loops) stop execution and the method ends.

public static void main(String[] args) {
        int x = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                if(j < i) j = j + n;
                else x = x+1;
            }
        }
    }

My confusion lies in why the time complexity is O(n) when both loops iterate to n at some point, i always iterates to n and j iterates to n when i = 0... Should it not be O(n^2) as we are multiplying nxn?

like image 923
CosmicCat Avatar asked Apr 26 '19 01:04

CosmicCat


People also ask

What is wrong with nested loops?

Nested loops increase cyclomatic complexity (see here), which decreases the maintainability of a program, according to some people.

What is the big O notation of three nested for loops?

Three nested loops: O(n³) In the above three nested loop, outer loop runs n - 1 time and two inner loops run n - i and j - i + 1 time.

What is the average time complexity of a nested for loop?

Every time the outer loop executes, the inner loop executes M times. As a result, the statements in the inner loop execute a total of N * M times. Thus, the total complexity for the two loops is O(N2).

How many nested loops is too many?

Microsoft BASIC had a nesting limit of 8. @Davislor: The error message refers to the stack size in the compiler, which is also a program, and which is recursively processing the nested-looped construct.

Is the complexity of an algorithm linked to the number of loops?

You seem to think that the complexity of an algorithm is linked to the number of nested loops. It is not the case. The following piece of code is O (1): for i in [1.. 10^15]: for j in [1.. 10^15]: for k in [1.. 10^15]: dosomethingO1 () Complexity is related to the rate of growth of the number of operations.

Is the complexity of a nested loop always constant?

I know however that nested loops can have a different complexity. For instance the following is in O (n.log (n)) It is not. Recall that so that the complexity of your loop is O (n²) and not O (n.log (n)). Yes. But by changing the data, you are also changing the n. In your fist example, the n is actually constant.

How many iterations in a nested loop?

Working throughout a variety of projects, it's not rare to stumble on pieces of code like the following, a "nested loop", which is a loop under another loop: Analysing the above code, and assuming we have 100 groups and 100 users: for each group (100 times) we iterate over all users (100 times), which leads 100 * 100 = 10000 iterations

Does unrolling a loop reduce the complexity of the loop?

Unrolling your loop does not change that. So: Has 0 (1) if the number of elements in myArray is bounded. The complexity will be decided by the number of iterations in the while loop. About your grid example: if n is the number of cells and your grid is represented as a nested array, looping over those arrays still yields O (n) complexity.


2 Answers

The innermost condition, if (j < i), is always true when i >= 1, as j is initialized to 0. Because you increment j by n inside the if-statement, this is equivalent to calling break;, thus exiting the innermost for-loop after a single iteration.

So to answer your question, the time complexity is O(n) because the innermost for-loop will only iterate 2n - 1 times:

  • It iterates to n when i == 0.
  • When i > 0, it only iterates once.

Thanks for Phoenix1355 for pointing this out below in the comments.

like image 84
Jacob G. Avatar answered Nov 06 '22 06:11

Jacob G.


You can also analyze the time complexity by passing different inputs (n). I copied the same code and created a separate function:

private static void testComplexity(int n) {
    int x = 0;
    int N1 = 0, N2 = 0;
    for (int i = 0; i < n; i++) {
            N1++;
        for (int j = 0; j < n; j++) {
                N2++;
            if(j < i) j = j + n;
            else x = x+1;
        }
    }
    System.out.println("input is : " + n + " and N1 " + N1 + " and N2 : " + N2);
}

public static void main(String[] args) {
    int[] inputs = new int[]{10, 100, 1000, 10000};
    for(int input : inputs) testComplexity(input);
}

The output is:

input is : 10 and N1 : 10 and N2 : 19
input is : 100 and N1 : 100 and N2 : 199
input is : 1000 and N1 : 1000 and N2 : 1999
input is : 10000 and N1 : 10000 and N2 : 19999

I created another function for QUADRATIC

    private static void testComplexity2(int n) {
    int N1 = 0, N2 = 0;
    for (int i = 0; i < n; i++) {
            N1++;
        for (int j = 0; j < n; j++) {
                N2++;
        }
    }
    System.out.println("input is : " + n + " and N1 " + N1 + " and N2 : " + N2);
}

The output is :

input is : 10 and N1 10 and N2 : 100
input is : 100 and N1 100 and N2 : 10000
input is : 1000 and N1 1000 and N2 : 1000000
input is : 10000 and N1 10000 and N2 : 100000000

Do you see difference ?

like image 22
royalghost Avatar answered Nov 06 '22 05:11

royalghost