Reputation: 31
What is the Big O notation of this function (as a function of n = len(lst)):
def foo(lst):
jump = 1
total = 0
while jump < len(lst):
for i in range(0, len(lst), jump):
total += i
jump = jump * 2
return total
I thought it was O(n*log(n)) but it's not, trying to understand why it's actually O(n)... I'm kinda new in this so if you could also explain how you got to the answer it'll be the best! thanks
Upvotes: 2
Views: 165
Reputation: 27588
You keep doubling your step: 1, 2, 4, 8, ...
So those ranges range(0, n, step)
that you go through have sizes n, n/2, n/4, n/8, ... (well, approximately - rounded to ints).
The sum of those is 2n (approximately). Which is O(n).
If you didn't know that sum yet, yet, it's easy to see: You start with 0. Then n gets you halfway to 2n. Adding n/2 gets you to 1.5n, again halfway to 2n. Adding n/4 gets you to 1.75, again halfway to 2n. And so on. You only get closer and closer to 2n.
Upvotes: 2
Reputation: 260490
The function is O(n).
The function makes about 2*n iterations to got into details (but 2*n
is n
in big O notation).
For each while
loop you're jumping to the next power of 2, so for example for n=1000
:
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]
Then for each subloop, you go through all element, thus effectively doing sum(successive_powers)
(in the example 1+2+4+…+512
= 1023
).
The sum of the n first powers is roughly the power of the n+1, so here: 2**(log2(n)+1)
~ 2*n
.
An easy way to check this is to change the code:
def foo(lst):
jump = 1
total = 0
while jump < len(lst):
for i in range(0, len(lst), jump):
total += 1 # count instead of summing
jump = jump * 2
return total
foo(list(range(1000)))
# 2000
Upvotes: 0