1

Determine the precise Big-Oh values for the following code sample, based on the number of statement executions.

Keep the following considerations in mind:

  • Remember to consider each statement in compound statements separately.
  • Pay close attention to the initial and end values of loop variables!
  • Loops such as “for” and “while” contain an implicit “jump” instruction that causes execution to proceed from the end of the loop back to the beginning of the loop.

Code sample:

for (int i = 0; i < n; i++){
   for (int j = i; j < n; j++){
      sum += i;
   }
}

The answer above is O(4N^2 + 5N + 2), but I am not entirely sure how the answer is counted. I am trying to better understand how to count the executions.

Vishwa Ratna
  • 5,567
  • 5
  • 33
  • 55
TS1000
  • 31
  • 6
  • 8
    Possible duplicate of [What is a plain English explanation of "Big O" notation?](https://stackoverflow.com/questions/487258/what-is-a-plain-english-explanation-of-big-o-notation) – Dang Nguyen Jan 16 '19 at 07:54
  • 1
    O(4N^2 + 5N + 2) is just O(N^2)... – Sweeper Jan 16 '19 at 07:58
  • 1
    From where 4 and 5 came? – Vishwa Ratna Jan 16 '19 at 07:59
  • That is what I am confused about as well. My teacher is asking for the 'precise' amount of executions. – TS1000 Jan 16 '19 at 07:59
  • This question is not duplicate but rather a subset of theoretical concept . – Vishwa Ratna Jan 16 '19 at 08:00
  • 3
    The Big O Misunderstanding aside, I don't think anyone without access to the course material will be able to answer this. If they want "jump to top of loop" counted as a separate instruction, this become very, very specific. For example, how do you know if the increment and comparison in the loop condition will be separate instructions or a combined one? I suppose since it is tagged Java, you could count the bytecode instructions? But even that seems compiler-dependent. – Thilo Jan 16 '19 at 08:42
  • 1
    Precise and Big-Oh are quite contradictory. If this was asked *as such* by your teacher, get another. –  Jan 16 '19 at 13:46

3 Answers3

2

As noted by Stephen the actual algorithmic complexity is simplified to O(N^2) but since your question was about measuring the amount of executions, i'll try and count them for you.

for (int i = 0; i < n; i++){
   for (int j = i; j < n; j++){
      sum += i;
   }
}

Firstly the outer loop

int i=0 will only be executed once.

i < n will be executed n+1 times

i++ will be executed n times

Therefore we have 2n+2 executions for the outer loop.

Let's clear something first. The outer loop will run n times and the inner loop will run n/2 times (on average). Therefore each instruction in the inner loop will be executed n * n/2 = (n^2)/2 times.

The inner loop

int j = i will be executed n times (remember it's in a loop)

j< n will be executed n+1 * n/2 = (n^2)/2 + n/2 times

j++ will be executed n*(n/2) = n^2/2 times

Now, remember each instruction in the inner loop will run (n^2)/2 times.

sum += i is basically 2 executions that will be executed n^2/2 times each. So this adds another n^2 executions

Adding them in total: (2n + 2) + n + (n^2)/2 + n/2 + (n^2)/2 + n^2 = 2n^2 + (7/2)n + 2

Adding the jump instructions which are n for the outer loop and n^2/2 for the inner loop we get the total of (5/2)n^2 + (9/2)n + 2.

Well either me or your professor has missed something , hopefully this helps a little though since it might give you an idea on how to count the amount of executions. I don't know why that's useful though

Nikos Tzianas
  • 633
  • 1
  • 8
  • 21
  • 1
    I will definitely try to double check the specifics but I believe this answer makes the most sense to me. Definitely a good start. Thank you. – TS1000 Jan 16 '19 at 09:55
  • @TS1000 for the other code you showed the only thing that changes is the inner loop will execute `n` times instead of `n/2` . Start with that and i'm sure you'll figure out something – Nikos Tzianas Jan 16 '19 at 13:47
  • Thank you. I will double check. – TS1000 Jan 16 '19 at 13:50
  • This accounting makes little sense as the exact count of elementary instructions per language construct is not specified. –  Jan 16 '19 at 13:50
  • @YvesDaoust Since it wasn't specified the best i can do is make some assumptions with what was given. Getting the exact correct result isn't the point and like you pointed out, it's impossible. The basic idea stays the same though. – Nikos Tzianas Jan 16 '19 at 13:56
1

The Big O for the complexity of that code is O(N^2). Any other answer is based on a misunderstanding of the mathematical definition of Big O notation and / or the conventions for writing it1.

You say that "the answer above is O(4N^2 + 5N + 2)". That's incorrect. It may be that the instruction count (according to certain assumptions about instructions and compilers) is 4N^2 + 5N + 2. However, that's NOT the conventional way to write the Big O complexity class for the function.

A complexity class is not a function. It is an infinite set of functions that satisfy a specific mathematical property. The convention is to use the simplest of all of the functions in the set to characterize the complexity class.

1 - Some people argue that it is not incorrect to use non-standard / non-conventional Big O notation. However, that defeats the purpose of using a mathematical notation ... which is the clear communication of mathematical ideas from one person to another. Analogy: if I wrote 1 + 1 is 11, I may be technically correct (using unary notation), but this an epic fail as means of communicating the idea 1 + 1 = 2.


My teacher is asking for the 'precise' amount of executions.

Well:

  1. That's NOT Big O.

  2. It is not a particularly useful measure, since the actual instruction count on real hardware after real compilation with a real compile will be different.


You say:

I believe each line of code has a certain amount of executions

The problem is that the number of "executions" depends on how you define what the primitive operations are, and how you compile the Java code to primitive operations.

For example, there are different ways to compile the nested loops in your example into instructions that will give different numbers of primitive jumps to be performed. (Think loop unrolling and / or a massive switch statement.)

This is illustrated by Nikos's answer. He has done a careful accounting of the instructions (according to his interpretation of what the primitive operations are) and come up with a different formula to your teacher. Who is correct? Probably both ... depending on the assumptions.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
1

You say the answer is O(4N^2 + 5N + 2) , but in fact answer,if reduced to BIG O will be O(N^2).

O(4N^2+5N+2+anythinglessthan N^2) reduces to O(N^2).

I will try to give you a hint if in future you are struck in finding complexities in a loop.

1. Time complexity of a function is considered as O(1) if it doesn’t contain loop, recursion and call to any other non-constant time function, in your case sum += i;

2. Time Complexity of a loop is considered as O(n) if the loop variables is incremented / decremented by a constant amount, in your case inner loop will have complexity O(N) if taken individually.

3. Time complexity of nested loops is equal to the number of times the innermost statement is executed. In your case O(N^k) -> O(N^2)

Combining 1+2+3 will give you the upper bound as O(N^2)

Vishwa Ratna
  • 5,567
  • 5
  • 33
  • 55