I am getting confused about how to analysis the time complexity within a nested while loop which divide into odd and even situation. could anyone help to explain how to deal with the situation?
i = 1
while (i < n) {
k = i
while ( k < n ) {
if ( k % 2 == 1 )
k ++
else
k = k + 0.01*n
}
i = i + 0.1*n
}
So in a problem like this, the factors 0.01 and 0.1 play a huge role.
First let's consider the inner while loop, if k is odd, we increment k by 1. If k is even, we increment k by one-hundredths of n. How man iterations can this inner while loop run?
Clearly if all iterations were of type-1(odd case), the inner while loop would run n-k times, and similarly if all the iterations were of type-2(even case), the inner while loop would run atmost a 100 times(as we increment the value of k by one-hundredths of n each time).
Given value of k, the number of iterations of the inner while loop is:
max(n-k,100). From now on, we will assume the value of n-k to be greater than 100 always, without loss of generality.
Okay, how does the outer loop iterate? In each iteration of the outer loop, the value of i increases by one-tenths of n each time, so the outer while will run at most 10 times.
Making the running times explicit and calculating the overall running time:
Running time for first iteration of outer loop : n-k
Running time for second iteration of outer loop : + n-(k+0.1*n)
+ n-(k+0.2*n)
...
+ n-(k+0.9*n)
-----------
= 10n-10k-(4.5)n
Plugging in k=1(as this is the start value of k),
10n-10-4.5n = 5.5 n -10 = O(n)
Hence complexity is O(n) time.
Related
x = 1;
while(x<n)
{
x = x + n / 10;
m = n*n
y = n;
while(m>y)
{
m=m-100;
y=y+20;
}
}
The way I solved it: we are adding to x 1/10 of n every time, so no matter how big n will be, the number of repitation we are doing is always 10.
The inner loop is from n to n^2, and each variable in it is increasing linearly, so the inner loop should be O(n)
and because the outer loop is O(1), we get O(n) for all of the function.
but the optional answers for the question are: O(n^2), O(n^3), O(n^4), O(nlogn)
What am I missing? thanks.
You are correct that the outer loop runs a constant number of times (10), but your reasoning about the inner loop isn't all the way there. You say that there is a "linear increase" with each iteration of the inner loop , and if that were the case you would be correct that the whole function runs in O(n), but it's not. Try and figure it out from here, but if you're still stuck:
The inner loop has to make up the difference between n^2 and n in terms of the difference between m and y. That difference between m and y is reduced by a constant amount with each iteration: 120, not a linear amount. Therefore the inner loop runs (n^2 - n)/120 times. Multiplying the number of times the outer loop runs by the times the inner loop runs, we get:
O(10) * O((n^2 - n)/120)
= O(1) * O(n^2)
= O(n^2)
The complexity of this code is O(log(n^2)*log(n), and i don't understand how we arrive to this result.
According to me, the nested while's big O should be just log(n) since its a while loop and we divide j by 4 everytime we enter the loop, and same for the initial while loop with i divided by 2. I especially dont understand which while loop has the O(log^2(n)) complexity
c = 0
i = n * n
while i > 0:
j = n
while j > 0:
c += 1
j = j//4
i = i//2
print c
I seem to be coming up with O(log_4(n)*log_2(n)) as the complexity. First, appreciate that the outer and inner while loops are not correlated. That is to say, the outer loop in i is independent of the inner loop in j. Here are the complexities of the outer and inner loop, in terms of n:
outer loop: O(log_2(n)). This is because the loop starts with n^2, and then decrements the counter by factors of 2, which is therefore log_2 behavior. As #chepner has commented:
O(log_2(n^2)) == 2*O(log_2(n)) = O(log_2(n))
inner loop: O(log_4(n)). This loop begins at n, and decrements the counter by factors of 4, which is log_4 behavior.
Your current guess is almost right, except that you might have missed the bases of the logarithms.
Function f(n)
s = 0
i = 1
while i < 7n^1/2 do
j = i
while j > 5 do
s = s + i -j
j = j -2
end
i = 5i
end
return s
end f
I am trying to solve the running time for big theta with the code above. I have been looking all over the place for something to help me with an example, but everything is for loops or only one while loop. How would you go about this problem with nested while loops?
Let's break this down into two key points:
i starts from 1, and is self-multiplied by 5, until it is greater than or equal to 7 sqrt(n). This is an exponential increase with logarithmic number of steps. Thus we can change the code to the following equivalent:
m = floor(log(5, 7n^(1/2)))
k = 0
while k < m do
j = 5^k
// ... inner loop ...
end
For each iteration of the outer loop, j starts from i, and decreases in steps of 2, until it is less than or equal to 5. Note that in the first execution of the outer loop i = 1, and in the second i = 5, so the inner loop is not executed until the third iteration. The loop limit means that the final value of j is 7 if k is odd, and 6 if even (you can check this with pen and paper).
Combining the above steps, we arrive at:
First loop will do 7 * sqrt(n) iterations. Exponent 1/2 is the same as sqrt() of a number.
Second loop will run m - 2 times since first two values of i are 1 and 5 respectively, not passing the comparison.
i is getting an increment of 5i.
Take an example where n = 16:
i = 1, n = 16;
while( i < 7 * 4; i *= 5 )
//Do something
First value of i = 1. It runs 1 time. Inside loop will run 0 times.
Second value of i = 5. It runs 2 times. Inside loop will run 0 times.
Third value of i = 25. It runs 3 times. Inside loop will run 10 times.
Fourth value of i = 125. It stops.
Outer iterations are n iterations while inner iterations are m iterations, which gives O( 7sqrt(n) * (m - 2) )
IMO, is complex.
I am reviewing some Big O notation for an interview and I come across this problem.
for i = 1 to n do:
j = i
while j < n do:
j = 2 * j
simple right? the outer loop provides n steps. and each of those steps we do a single step O(1) of assignment j=i then log(n-j) or log(n-i) since j = i step for the while loop. I thought the time complexity would be O(nlogn) but the answer is O(n).
here is the answer:
The running time is approximately the following sum: Σ 1 +
log(n/i) for i from 1 to n which is Θ(n).
Now it has been a while so I am a bit rusty. where does log(n/i) comes from? I know log(n) - log(i) = log(n/i) however I thought we log(n-i) not log(n) - log(i). and how is the time complexity not O(nlogn)? I am sure I am missing something simple but I been staring at this for hours now and I am starting to lose my mind.
source: here is the source to this problem Berkeley CS 170, Fall 2009, HW 1
edit: after thinking about it a little more it makes sense that the time complexity of the inner loop is log(n/i). cause each inner loop runs n-i times but i double each loop. if the inner loop were always starting at 0 we have log(n) but take into account the number of the loop we don't have to loop over which is log(i). log(n) - log(i) which is log(n/i).
I think the log(n/i) comes from the inner loop
notice how j = i
which means when i=2 (lets say n=10)
the inner loop
while j < n do:
j = 2 * j
will run only from j=2 to 10 where j multilplies itself by 2 (hence the log) & quickly overruns the value of n=10
so the inner loop runs log base 2 n/i times
i ran a simple i=10 through the code & it looks like linear time because most of the time inner loop runs only once.
example : when the value of i becomes such that if you multiply it by 2, you get greater than or equal to n, you don't run the inner loop more than once.
so if n=10 you get one execution in the inner loop starting from i=n/2 (if i=10/2=5) then j starts with j=5, gets in the loop once multiplies itself with 2 & the inner loop condition while j < n do: fails.
EDIT : it would be O(n.log(n)) if the value of j started with j=0 everytime & the inner loop ran from i to n
Assuming do_something is O(1), how do I calculate the time complexity of this function?
function run(n) {
for(var i = 1; i <= n; i++) {
var counter = 1;
while(counter <= n) {
for (var j = counter; j >= 1; j--) {
do_something();
}
counter = counter * 2;
}
}
}
I'm assuming the initial for loop means the that the complexity will be n and the inner while loop means log(n). Is this true?
How do I calculate the complexity of everything?
Thanks.
It's not trivial to calculate the complexity of everything because there are functions (e. g. collatz conjecture) where no exact analysis is known. In such a case you can do an empirical analysis where you guess which run time class would match best.
Related to your sample:
The outer for loop is called n times
The while loop is called log(n) times
The inner for loop is called counter times where counter grows 2^m. But counter is recalculated log(n) times
That means the inner exponential for loop (2^m) is called m=log(n) times.
So you have 2^(log n) = n log(2) = n
You can also do it vice versa. The inner exponential function is called log times. Means log(2^m) -> (2^n = 2^m) -> m = n.
You can also simply create a sum of 2^m from m=0 to m=log(n) which is 2n-1 -> O(n).
Then you have to multiply linear time of outer for loop with linear time of while loop (incl. inner for loop). So you have O(n*n) = O(n²) time.
The exact amount of steps can be calculated.
The outer loop runs n times
The while and inner-most loop is run counter times for each of the values of counter, these are 1, 2, 4, 8, ..., 2^(bitLength(n)-1)
which sums to 2^bitLength(n) - 1
where bitLength(n) = trunc(ln(n)/ln(2))+1
Multiplying these two, yields the exact amount of steps:
n * (2^bitLength(n) - 1)
The approximate complexity is O(n2), because O(2^bitLength(n) - 1) = O(n)