Finding the complexity of Loops - algorithm

I'm given this algorithm and I'm told to find the complexity of it big theta.
for (i = 1; i <= n; i++) {
j = n;
while( j >= 1) {
j = j/3;
}
}
I know outer for loop runs n times. The while loop is more tricky though, Is it possibly log n (of base 3). In total making it n*log3n
Is this correct?

There is an outer for loop of size n. It contributes a complexity of a factor of n to the over all complexity.
Let's say inner while loop runs for m times. After i'th iteration, the value of j will be n/(3^i). We will run this till n/(3^i) > 1. Therefore,
=> n/(3^i) = m
=> n = 3^m
=> log(n) = log2(3) * m
=> m = O(log(n))
So, for loop contributes to O(n) and while loop contributes to O(log(n)). Complexity of nested loop becomes O(n log(n)).

Related

Time complexity of dependent nested loops

I was trying to find the time complexity of this nested loop
for (i = 1; i <= n; i++) {
for (j = 1; j <= n; j++) {
n--;
x++;
}
}
If there wasn't a n-- it would be n*n , O(n2) right?
But what if n reduces every time second loop runs?
What's the time complexity and big O of this nested loop?
If I consider n = 5, x equals 4, the second loop runs 4 time
The time complexity of the code is O(n). n is reduced by half for every iteration of the outer loop.
So we have n/2 + n/4 + n/8 + n/16 + ... + n/2^k = O(n)
where k is the number of iterations of the outer loop (basically i).
Note that the time complexity is independent of x.
If there wasn't a n-- it would be n*n , O(n2) right?
Yes
Another way to see it's O(n): You only enter the inner loop body if j <= n, and since j is positive, n must also be positive. But you decrease n every time, which you can only do O(n) times (where n is the starting value) and still have n positive.

When do you multiply by the average Big O of nested loop?

When do we multiply the Big O of the outer loop by the average Big O of the inner loop?
for (int i = n; i > 0; i /= 2) {
for (int j = 0; j < i; j++) {
//statement
}
}
Answer: O(n)
In this question, the outer loop is O(log n). Since the inner loop executes some number of times based on 'i', the average Big O is taken. This results in a summation of n + n/2 + n/4 + ... = 2n which is then divided to get the average: O(2n / log n).
Hence O(log n) * O(2n / log n) = O(n).
But then why don't we need to take the average for this question?
for (i = 0; i < n; i++) {
for (j = 0; j < i * i ; j++){
}
}
Answer: O(n^3)
The outer loop is O(n). The inner loop is O(n^2). But why?
Doesn't the inner loop execute based on a value of 'i' in the outer loop? So why isn't the average taken like the question above? - resulting in something like O(n^2 / n) for the inner loop.
The complexity of an algorithm is determined by counting how many operations it performs when executed. For a loop which iterates k times, where m is the mean number of operations on each iteration, the total number of operations performed is always total = k * m, simply because the mean is defined to be m = total / k.
It also makes sense to do this in big O notation: if a loop iterates O(k) times, and performs a mean of O(m) operations on each iteration, then the total number of operations is O(k * m).
The problem is that in your second example, you are not calculating the mean correctly. When you say "The inner loop is O(n^2)", this is already the mean; you are considering the number of iterations of the inner loop for one iteration of the outer loop. The total number of iterations is O(n^3), and the number of iterations of the outer loop is n, so the mean is O(n^3 / n) = O(n^2) as expected.
It is more natural to do this calculation the other way around: after observing that the mean is O(n^2), and the outer loop iterates O(n) times, the total is O(n^2 * n) = O(n^3).

What is the big-O of this program where nested loops depend on each other?

Can't figure out what the big O for this block of code is. Outer loop is log(n), but how bout inner loop that depends on outer loop?
for (int i = 1; i < A.length; i = i * 3) {
for (int j = i; j < A.length; j++) {
// Simple computation
}
}
Any help greatly appreciated :)
If A.Length == n, the inner loop runs in n-i each time. Hence, the total complextiy of the program is sum(n - i) for i = 1, 3, 9, ..., n = 3^log_3(n). As the number of i is log_3(n), the complexity is T(n) = n * log_3(n) - (3^(log_3(n)+1)-1) = n * log_3(n) - 3(n-1) = O(nlog(n))
As is your code will not complete because i = i * 3 means that i will always be 0.
From your comment it is supposed to be i = 1. So, on each iteration of the outer loop, the problem size is reduced by a constant factor of 3. This means that the outer loop takes O(log n) steps.
The inner loop takes O(n) in the worst case and is run O(log n) times. Therefore, the entire running time is O(n log n).
Be sure to check your post for typos and do some research in the future :).

Time complexity of nested for loop with inner iteration variable dependent on the outer one

This is the loop structure :
for (int i = 1 ; i < n ; i++) {
for (int j = 0 ; j < n ; j += i) {
// do stuff
}
}
My guess was O(nlogn) as it clearly cannot be O(n^2) since the increment in j is increasing and it clearly cannot be O(n sqrt(n)) since the increment is not that high. But I have no idea how to prove it formally.
Each time complexity of the inner loop is based on the value of i is n/i. Hence, total time would be n + n/2 + n/3 + ... + n/n = n(1+1/2+1/3+...+1/n).
As we know 1+1/2+1/3+...+1/n is a harmonic sereis and asymptotically is log(n). Hence, the algorithm is run in O(nlog(n)).

Complexity of a nested geometric sequence

Below code is actually bounded by O(n^2), could anyone please explain why?
for (int i = 1; i < n; i++) {
int j = i;
while (j < n) {
do operation with cost O(j)
j = j * 3;
}
}
It's not that tricky.
Your inner loop's complexity forms a geometric progression with total omplexity O(n).
Without filling the details all the way (this seems like a HW problem), note that the formula for a geometric sequence is
a_0 (q^k - 1) / q - 1, (a_0 = first element, q = multiplication factor, k = num elements).
and your q^k here is O(n).
Your outer loop is O(n).
Since it's a nested loop, and the inner term does not depend on the outer index, you can multiply.
The proof is geometric progression :)
For i = n, the inner loop doesn't execute more than once if i > n/3 (because in next iteration j is >= n).
So for 2n/3 iterations of outer loop the inner loop iterates only once and does O(j) operation. So for 2n/3 iterations the complexity is O(n^2).
To calculate complexity of remaining iterations set n = n/3, now apply steps 1, 2 and 3
Methodically, using Sigma notation, you may do the following:

Resources