Say we have this algorithm in Python.
def secret(S: list):
n = len(S)
while n > 0:
n = n // 2
for j in range(n):
if j in S:
S.append(j)
return S
I need to find the strictest upper bound (Big-$O$).
I have two approaches to solve this, which give me different solutions and I would appreciate your help deciding which one is correct!
The first approach:
According to the python documentations, the x in s
operator is $O(n)$ where $n$ is the length of the list.
(Provided here: https://wiki.python.org/moin/TimeComplexity)
So, at the worst case, in each of the for loop, we search the element $|S|$ times. Say that $|S| = N$, then in each iteration the length of $S$ at the worst case gets bigger by $1$ - because it does contain $j$ each time, and it adds this $j$.
The first iteration of the while loop
: $\text{range}(N/2)$
$$ N + (N+1) + (N+2) + \dots + N + \frac{N}{2} = \frac{N^2}{2} + 1 + 2 + \dots + \frac{N}{2} = \frac{N^2}{2} + \frac{\frac{N}{2}(\frac{N}{2} + 1)}{2}$$
At the second iteration of the while loop
: $\text{range}(N/4)$
$$N + \frac{N}{2} + (N + \frac{N}{2} + 1) + (N + \frac{N}{2} + 2) + \dots + (N + \frac{N}{2} + \frac{N}{4}) = \frac{N^2}{4} + \frac{N^2}{8} + 1 + 2 + 3 + \dots + \frac{N}{4} = \frac{N^2}{4} + \frac{N^2}{8} + \frac{\frac{N}{4}(\frac{N}{4} + 1)}{2}$$
The $k$-th iteration is by:
$$I_k = \frac{N^2}{2^k} + \frac{N}{2^{k-1}} \cdot \frac{N}{2^k} + \sum_{i=1}^{N/2^k} i$$
and over and over... exactly $\lg(N)$ times.
$$ \sum_{k=1}^{\lg(N)} I_k$$
Which is (if I am not wrong here): $$O(N^2 \lg (N))$$
The second approach:
The second approach is like the first, but I noticed that while it's true that the x in S
operator is $O(|S|)$, it is not $|S|$ (the current size) in this case specifically, as we insert these numbers if they are already in the array! so each iteration will be at most $O(N)$ and not $O(|S|)$
And so the math gets easier and we do on the first iteration:
$$\overset{N/2 \text{ times}}{N + N + N + \dots + N} = N^2 / 2$$
On the second iteration it would be:
$$\overset{N/4 \text{ times}}{N + N + N + \dots + N} = N^2 / 4$$
and this keeps going of course, $\lg(N)$ times, so we have this sum:
$$ \sum_{k=1}^{\lg(N)} N^2 / 2^k$$
Which at the end goes to be:
$$O(N^2)$$
Which one is correct?
When we recognize the 'live' updating size of $N$ (starting at $N$, then $N+1$, then all the way to $N+N/2$, then $N+N/2+1$ all the way to $N+N/2+N/4$, ...)
Or not recognize the live updating size, as the in
operator would surely find the number at most $N$ iterations? ($N$ is the starting size of $S$.)