Say I have the following for loops:
for (int i = 1; i < n; i*=2) {
for (int j = 1; j < i; j*=2) {
//constant functions here
}
}
The outer loop will run log(n) times, my question is about how many times the inner loop will run. We can approximate j to be 2s, for some s, and it will stop when 2s < i, which can again be approximated to 2r, for some r. If we take the log of both sides, we get that s < r, which is when the second for loop will stop. Based on this, can we say that the inner loop runs constant times? And that the total number of times this function will run is just log(n)?
First neglect the outer loop, suppose the value of i =4, the inner loop will run for log(4) times, generalizing the inner loop will run log(i) times,for different values of i. Now consider the outer loop, value of i changes log(n) times. Hence the complexity is log(n)*log(i) or just simply (log(n))^2
in one word the answer is : Log2(n)2
Proof
consider Log2(n) = k so we have in first iteration of outer loop, inner loop runs 1 time because i = 2, in second iteration inner loops runs 2 times because i = 4, and ... in k'th iteration of outer loop, inner loop runs k times because i = 2k so number of your iterations:
1 + 2 + ... + k = k(k+1)/2
so the answer is O(Log2(n)2)
Related
I'm trying to understand the growth function of this code.
for (int count=0; count < n; count++) {
for (int count2=1; count2 < n; count2=count2*2) {
System.out.println(count + ", " + count2);
}
}
The outer loop is linear since you're incrementing by one each time. The inner loop is log(n) since your upper bound would have to increase exponentially to keep up with the growth of the count2 variable therefore the entire nested iteration is nlog(n) .
A good way to approach these problems when you're just starting to learn about growth and order is by thinking about it visually. Refer to the diagram and explanation below:
Assume n = 8 and printing is a constant time operation.
Look at the loops separately first.
The outer loop is fairly trivial:
we start with a count of 0, and increment count by 1 each time until we reach n = 8. Therefore, we must increment 8/1 = 8 times in order to complete the loop. Generalized to n, the loop will run for n times.
The inner loop is slightly more involved:
we start with a count of 1 and increment by multiplying 2 to count2 until we reach n = 8. In this way, count2 increases by a factor of 2 at each iteration and its value can be determined by 2^k where k is the number of iterations. To figure out how many iterations it will take to reach n = 8, solve 2^k = 8 or k = log2(8) = 3. Generalized to n the loop will run for log2(n) times.
Combining these two facts, the inner loop will be run for every iteration of the outer loop so all in all, it will take n * log2(n) to run. Therefore, the runtime complexity is O(nlog(n))
I have the code below and am trying figure out the big O worst case running time for it. I think that the first loop is O(log N), but I am not sure what the second loop is. I thought maybe it was O(N) but that didn't seem right. Any insights would be very helpful.
for(int jump = inList.size(); jump > 0; jump/= 2) {
for(int i = 0; i < inList.size(); i = ++i * jump) {
This is going to be a O(log(n)) algorithm because the outer loop is clearly O(log(n)) and for large enough N the inner loop is going to finish executing in constant (2) iterations because n/2 * (n+1)/4 = (n^2+n)/8 > n for n > 6. For all values greater than 6 the inner for loop always iterates twice, big O deals with large cases (approaching infinity) in which case the inner loop is constant.
I know this is easy but my textbook doesn't talk about Big-Oh order with do-while loops, and neither do any of my other algorithm sources.
This problem states that the following code fragment is parameterized on the variable "n", and that a tight upper bound is also required.
int i=0, j=0;
do {
do {
System.out.println("...looping..."); //growth should be measured in calls to println.
j=j+5;
} while (j < n);
i++;
j = 0;
} while (i < n);
Can anyone help me with this and explain Big-Oh order in terms of do-while loops? Are they just the same as for loops?
A good maxim for working with nested loops and big-O is
"When in doubt, work from the inside out!"
Here's the code you have posted:
int i=0, j=0;
do {
do {
Do something
j=j+5;
} while (j < n);
i++;
j = 0;
} while (i < n);
Let's look at that inner loop. It runs roughly n / 5 times, since j starts at 0 and grows by five at each step. (We also see that j is always reset back to 0 before the loop begins, either outside the loop or at the conclusion of an inner loop). We can therefore replace that inner loop with something that basically says "do Θ(n) operations that we care about," like this:
int i=0;
do {
do Θ(n) operations that we care about;
i++;
} while (i < n);
Now we just need to see how much work this does. Notice that this will loop Θ(n) times, since i counts 0, 1, 2, ..., up to n. The net effect is that this loop is run Θ(n) times, and since we do Θ(n) operations that we care about on each iteration, the net effect is that this does Θ(n2) of the printouts that you're trying to count.
How many times does this nested loop run. How do I determine it by looking at the code.
int i = 5, j =0;
while (i>0)
{
j = 1;
while (j<i )
{
System.out.println(“Inner loop!”);
j++;
}
System.out.println(“Outer loop!”);
i
Since you left out the -- from the i-- on the last row, this will never terminate.
well, first off, the code isn't complete, and depending on how it completes changes the answer completely. It should be something like:
int i = 5, j =0;
while (i>0)
{
j = 1;
while (j<i )
{
System.out.println(“Inner loop!”);
j++;
}
System.out.println(“Outer loop!”);
i++; // OR i--;
}
If the case is the final part is"i++" at the end it runs for an infinite number of times, because when "While(i>0) " evaluates, "i" never becomes less then 0. And "infinite" only in logic, as numbers (integers in this case) have a definite upper bound in code/compilers.
If its "i--" then its a simple matter of counting. The larger loop, [while (i>0)] will count down from 5 to 0, and quit when i is zero, that means it will will run with i=5, i=4, i=3, i=2, and i=1. This means effectively the outer loop runs 5 times, and each time it runs a little less.
J starts at 1 and counts up to just under i [while(j [lessthen] i)], meaning it will run the first time counting 1 to 4, because J starts at one, and goes to one-less-then i (5 the first time). So 4 the first time, 3 the second time, 2 the third time, 1 the forth time, and none the fifth time, because in that last case the evaluation is 1(j)[lessthen]1(i), which is false and exits the loop.
To get your final number, you count the number of times the inner loop happens successfully, in this case 4 + 3 + 2 +1 or....10 times. Assuming its "i--"
Our teacher in my AP Computer Science course gave us this code
final int LIMIT = 5;
int i, count;
for (count=1; count<=LIMIT; count++)
{
for (i=0; i<count; i++)
{
System.out.print(count);
}
}
System.out.println();
When this code executes, the output is as follows
1
22
333
4444
55555
I do not have a good understanding of the for statement and I cannot understand why the code would print 1 once, 2 twice, 3 three times, ect. Can someone please try to explain this to me?
This is a great question and covers the basics of for loops.
Thinking About For Loops: The Basics
Think about the code you have written above in this way:
A for loop does ("executes") what is enclosed in its body once for each time you specify - or, to think about it another way, until a condition that you specify is false. As the coder, you need to tell the program: [1] at what point to begin; [2] how many times to do it (better thought about as "until when to do it"); [3] and by how many the code should "count" (what we call "increment").
To demonstrate with pseudo-code:
for ([1]; [2]; [3])
or
for (where to begin; how many times; how to count) {
// DO SOMETHING
}
Remember, as you "count", you are increasing - in the case of the first for loop - the count variable by the how to count piece (count + how to count). What you have in your above code is a nested for loop - a loop inside another loop (described, below). Referencing the pseudo-code I have written, above, your first for loop does the following:
for (start counting at 1; iterate once until count is greater than 5; increment count by 1)
Your Question
Now, comes the piece that is throwing you. You have two variables to pay attention to because you have two for loops: count, in the first for loop (used by the second); i in the second. Each time your first for loop iterates, the first for loop must execute the second for loop (look at your code). Again, pay attention to the two variables - but, more importantly, the relationship between the variables in both for loops' conditions. The second for loop depends upon the first. Think about it this way:
As count is incremented (here, increased by one), the second for loop must execute its own operation that many times:
for (i starting at 0; i not equal to count; increment by 1)
So, at the first iteration you would see something like this:
for (count = 1; count will always iterate once until condition false; increment){ }
for (i = 0; i < count (1); increment i){ }
Result will be:
1
Then the first loop is incremented (count becomes 2) and you get:
for (i = 0; i < (2); increment i)
Because the second loop will iterate until i is no longer less than 2 (not including 2), your result will be:
22
This relationship will continue until you get your final result:
55555
A Final Comment
Your teacher is looking to teach you a few different things with the code you provided, above, namely two: nested for loops; and how initializing your iterator (i and count) and the condition statement <, >, <=, >=, etc.) affects the behavior of a loop.
The first for loop indicates that it will loop the contents LIMIT times(which is 5), incrementing count by 1 at the end of each loop. The second inner for loop indicates that number of times to print the number count.
Might be easier to understand with indentation of your code:
final int LIMIT = 5;
int i, count;
for (count=1; count<=LIMIT; count++) {
for (i=0; i<count; i++) {
System.out.print(count);
}
System.out.println();
}
The first for loop starts at 1 and ends at limit 5. The inner loop starts at 0 and goes to the current count. So for the first iteration the inner loop will go from 0 to 1. This will print count 1 time which count is 1. The second time through the outer loop the counter will be 2 so the inner loop will loop from 0 to 2. It will print 2 twice. The 3rd time through count will be 3. The inner loop will loop from 0 to 3 and print 3 3 times. Etc... This is nested looping.
The first loop will write 5 lines as LIMIT = 5
The second loop will write n times the current index of the first loop, for each line.
n equals the current index of the first loop. So line #1, one time 1, line #2, two times 2, ....
You have two for loops, the outer loop starts count with a value of 1 and will iterate until count has a value greater than 5. The inner for loop will start with a value of 0 and will iterate until i has a value greater than or equal to count. So,
count <- 1
i <- 0
while (i < count) { print(count); i++; } // <-- 0 to 1 is a range of 1
newline();
Then
count <- 2
i <- 0
while (i < count) { print(count); i++; } // <-- 0 to 2 is a range of 2
newline();
And so on.
It is probably best to explain this by walking through the steps on by one...
final int LIMIT = 5;
int i, count;
for (count=1; count<=LIMIT; count++)
{
for (i=0; i<count; i++)
{
System.out.print(count);
}
System.out.println(); //from the results you are getting, this statement should be here
}
To put this in human readable terms:
A. we have a number LIMIT that is 5
B. we have a number i and count
C. set the number count to 1
D. if the number count is less than LIMIT, do the following:
1. set the number i to 0
2. if the number i is less than the number count, do the following:
a. print out the number count
b. add 1 to the number i
c. go back to step 2
3. print out an empty line
4. add 1 to the number count
5. go back to step D
So, if we go through the loops, here's what our variables become:
count is set to 1
count is less than 5
i is set to 0
i is less than count? yes, i is 0 and count is 1
print out the value of count (which is 1)
add 1 to i
i is 1
is i less than count? no, i is 1 and count is 1
print out a new line
add 1 to count
count is 2
count is less than 5
i is set to 0
i is less than count? yes, i is 0 and count is 2
print out the value of count (which is 2)
add 1 to i
is i less than count? yes, i is 1 and count is 2
print out the value of count (which is 2)
add 1 to i
is i less than count? no, i is 2 and count is 2
print out a new line
add 1 to count
count is 3
etc.
This continues until count is greater than 5, at which point it exists. As you can see from the pattern, the variable count determines which number gets printed, and the variable i determines how many times it is printed.