views:

180

answers:

3

I need to state the big o of the following fragment:

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

I know the outer loop is O(n) but I am having a problem analyzing the inner loop. I think it's O(log n). I would appreciate any help. Thank you in advance.

+1  A: 

As Dave said, it's O(n log n) because the inner loop is O(log n).

Paul McMillan
Wow, that was fast; the question I responded to is gone :)
Dave
s/question/answer/
Dave
+6  A: 

Let's just write this in this pseudo-mathematical style.

sum i <- [1..n] (sum j <- [1..n/i] 1)

The inner loop (sum) needs

n / i

iterations, which makes the whole term

sum i <- [1..n] (n/i)

Simplify the sum according to the distributive law:

n * (sum i <- [1..n] (1/i))

The inner sum is largely similar to the integral over 1/x, which is logarithmic.

So O(n log n) is right.

Dario
+4  A: 

The best approach to this is to consider how many steps the algorithm will take.

If you have n elements, you know that the outer loop is going to run at least n times. So it has to be at least O(n).

How many times does the inner loop have to run for each i? Does it increase, stay the same or decrease as i increases?

It's clear that the number of steps in the inner loop will decrease as i increases, and more importantly, it decreases non-linearly. So you know it isn't as bad as O(n^2).

So it's somewhere between O(n) and O(n^2).... a bit more analysis on how the steps decrease in the inner loop should get you there. EDIT: ... Although it looks like people already gave it away :)

womp
This is a great explanation.
Dave
Actually, it could be O(n^2) (or more properly, Theta(n^2)) even if the number of steps in the inner loop decreases. For instance, think about the case where the inner loop is `n-i` steps (which is the case in the insertion sort algorithm, among others).
jk
What about `for i in 1..n for j in 1..i ...`? According to your explanation, this isn't `as bad as O(n²)`, because the inner loops range decreases as i increases, but it **actually is** O(n²)
Dario
@jk: Funny, just 17 sec difference^^
Dario
@Dario: didn't you just contradict your answer in this comment?
Dave
@dario and @jk - you guys are correct, I should have said "linearly decreases".
womp
@Dave: No, my comment describes a completely different for loop, not the one that has been asked for.
Dario
@Dave - no he's pointing out that my explanation is too simplistic. You can have a smaller inner loop that gets smaller linearly with the outer loop and it's still considered O(n^2). The number of steps has to be functionally related by an order of magnitude.
womp
@womp: Post edited, problem solved ;-) +1
Dario
Ok, reaching way back, I understand the discrepancy. Still, I think you got the gist of it the first time.
Dave