问题
Does anyone know of any good resources to learn big o notation? In particular learning how to walk through some code and being able to see that it would be O(N^2) or O(logN)? Preferably something that can tell me why a code like this is equal to O(N log N)
def complex(numbers):
N = len(numbers)
result = 0
for i in range(N):
j = 1
while j < N:
result += numbers[i]*numbers[j]
j = j*2
return result
Thanks!
回答1:
To start, let me define to you what O(N log N) is. It means, that the program will run at most N log N operations, i.e. it has a upper bound of ~N log N (where N is the size of the input).
Now here, your N is the size of numbers, or your code:
N = len(numbers)
Notice that the first for loop runs from 0 to N-1, for a total of N operations. This is where the first N comes from.
-
Then, where does the log N come from? It is from the while loop.
In the while loop, you keep multiplying 2 to j until j is greater or equal than N.
This will be completed when we have executed the loop ~log2(N) times, which describes how many times we have to multiply j by 2 to get to N. For example, log2(8) = 3, because we multiply j by 2 three times to get 8:
#ofmult. j oldj
1 2 2 <- 1 * 2
2 4 4 <- 2 * 2
3 8 8 <- 4 * 2
To better illustrate this, I have added a print statement in your code, for i and j:
def complex(numbers):
N = len(numbers)
result = 0
for i in range(N):
j = 1
while j < N:
print(str(i) + " " + str(j))
result += numbers[i]*numbers[j]
j = j*2
return result
When this is run:
>>> complex([2,3,5,1,5,3,7,3])
This is what is outputted:
0 1
0 2
0 4
1 1
1 2
1 4
2 1
2 2
2 4
3 1
3 2
3 4
4 1
4 2
4 4
5 1
5 2
5 4
6 1
6 2
6 4
7 1
7 2
7 4
Notice how our i goes from 0...7 (N times for a total of O(N) ), and the second part, there are always 3 ( log2(N) ) j-outputs for every i. So, the code is O(N log2 N).
Also, some good websites I would recommend are: https://rob-bell.net/2009/06/a-beginners-guide-to-big-o-notation/
And, a video from a lecture series from a Stanford professor: https://www.youtube.com/watch?v=eNsKNfFUqFo
回答2:
When you multiply j by 2, you're effectively saying "I've done half the remaining problem!". At each step in the while loop, you're solving half the remaining problem. Therefore if your problem is x
size, then the number of iterations required would be i = log_2 x
, which we just say is log x
. In this case your x is just equal to N.
The for loop has you do the above section N times again, so you get N * log N.
We use O(N log N) to mean that, at each step, we might do any CONSTANT number of things (for example inside the while loop I might do a billion operations), but we don't care about this constant, because generally N is usually bigger, and can get arbitrarily big (beyond a certain size point, even a billion is nothing in comparison to what N COULD be, i.e. a googol). Hence we have O(N log N).
Here's a short crash course in the form of a pdf:
http://www1.icsi.berkeley.edu/~barath/cs61b-summer2002/lectures/lecture10.pdf
Here's a short crash course in the form of a lecture:
https://www.youtube.com/watch?v=VIS4YDpuP98
来源:https://stackoverflow.com/questions/33536706/big-o-notation-in-python