A lot of College Board problems depend on being able to tell how many times a loop runs. Below I’ve cataloged a number of kinds of loops in order of increasing complexity with information about how to figure out how many times a loop will run using a bit of simple math. Note that if you skip to the section on “Step loops” and master the formula for the most general form it handles the first two kinds of loops as well.
Remember that counting loops can also be written as while loops. For those while loops you can use the formulas in this document as long as you identify the initializer (usually a variable declaration right before the while), the condition (that’s easy, it’s in the while), and the updater (usually the last line of the body). However not all while loops are simple counting loops. (For that matter, not all for loops are either so the first thing you may need to check when looking at any loop is whether it’s a counting loop in the sense of having a loop variable that starts at a number and goes to another number in uniform steps.)
These loops loop up or down from or to 0 or sometimes 1. They are the
most common loops, used to iterate over the elements of a
String
, array, or ArrayList
. You should be
able to look at loops like these, especially the three upward loops, and
tell almost instantly how many times the loop body will run.
Loop style | Number of iterations | Values of i |
---|---|---|
|
num | 0 up to num - 1, inclusive. |
|
num | 1 up to num, inclusive |
|
num | num down to 1, inclusive |
|
num + 1 | 0 up to num, inclusive. |
|
num + 1 | num down to 0, inclusive |
These loops are similar to simple counting loops but they start at some
arbitrary number other than 0 or 1. They are useful for iterating over a
substring of a String
or a subsection of an array or
ArrayList
. You have to do a bit of subtraction to figure
out how many times the loop body will run.
Loop style | Number of iterations | Values of i |
---|---|---|
|
end - start | start up to end - 1, inclusive |
|
(end - start) + 1 | start up to end, inclusive |
|
start - end | start down to end + 1, inclusive |
|
(start - end) + 1 | start down to end, inclusive |
The final generalization of counting loops, step loops are like range
loops with the added wrinkle that the loop variable is incremented or
decremented by some number other than 1. If start
. and
end
are multiples of step
these can be
converted to a simple or range loop and then in the body of the loop
instead of using the loop variable use the loop variable times
step
. This can often make the code easier to read because
it’s easier to understand how many times the loop will run just by
looking at the loop header.
If start
and end
are not multiples of
step
you need to think more carefully about when the loop
will end. But in either case the formulas below will let you figure out
with one subtraction, and one rounding division how many times the loop
body will run.
Loop style | Number of iterations | Values of i |
---|---|---|
|
(end - start) / step, rounded up | start plus multiples of step |
|
(start - end) / step, rounded up | start minus multiples of step |
|
((end - start) + 1) / step, rounded up | start plus multiples of step |
|
((start - end) + 1) / step, rounded up | start minus multiples of step |
Note that when the comparator is <
or
>
the number of iterations is the larger index minus the
smaller index divided by the step size and when it’s
<=
or >=
we subtract the smaller from
the larger and then add one before dividing by step size. And in either
case, we round up after dividing. This formula works for all the other
kinds of loops which are just more specific cases of these step loop
forms with step
being 1 and—in the case of simple loops—one
of start
or end
being 0 or 1 which makes the
subtraction pretty easy.
When we talk about how many times a nested loop runs we usually mean the body of the innermost loop. The only trick to analyzing such loops, is to correctly analyze both the outer and inner loops and then multiply the number of times each loop runs. For instance:
for (int i = 0; i < 10; i++) {
for (int j = 0; j < 12; j++) {
System.out.print("*");
}
}
It’s easy to see that the outer loop runs 10 times and the inner loop runs 12 times. Thus the call to System.out.print will happen 10 x 12 or 120 times.
Obviously if the loops are more complex it won’t be as easy to read off the number of times but we can still analyze each loop independently. Consider, for instance, this mess:
int i = 38;
while (i >= -17) {
for (int j = -13; j < 15; j += 3) {
System.out.print("*");
}
i -= 5;
}
We can analyze the outer loop as a step loop from 38 down to -17 by 5 with a >= in the condition. So ((38 - -17) + 1) / 5 or 56/5 which gives us a bit more than 11 so 12 iterations. And the inner loop is from -13 up to 15 by 3’s with a < in the condition so (15 - -13) / 3 or 28 / 3 which is 9 and a bit so rounding up gives us 10. Now 12 times 10 gives us 120 for the number of times the inner body of these nested loops will be run.
Below are some common patterns for traversing 1D and 2D arrays. These also work with ArrayLists, if you replace a.length with list.size()and a[i] with list.get(i). And the one-dimensional recipes work with Strings, if you replace a.length with s.length() and a[i] with s.substring(i, i + 1).
Loop style | Purpose |
---|---|
|
Traverse array in normal order. |
|
Traverse array in reverse order. |
|
Traverse 2D array from top left to bottom right by row (sometimes called “row major order”). I.e. processes all the elements in the 0th row, then all the elements in the 1st row, and so on. Assumes the 2D array is rectangular (i.e. all the rows are the same length). |
|
Same as previous but processes the rows from last to first. Columns are still left to right. (This is not a particularly common thing to do but the College Board likes to mix things up.) |
|
Traverse 2D array from top left to bottom right by column (sometimes called “column major order”). I.e. processes all the elements in the 0th column, then all the elements in the 1st column, and so on. Assumes the 2D array is rectangular (i.e. all the rows are the same length). |
|
Process each pair of elements in a 1D array, where pairs are processed in the both orders (e.g. a[0] and a[1] and also a[1] and a[0]. Will also process the pairs made of pairing each element with itself, i.e. a[0] and a[0]. |
|
Process each unique pair of different elements in a 1D array ignoring order. In each pair a[i] and a[j] the element earlier in the array comes first. Does not pair elements with themselves. |
Loop style | Purpose |
---|---|
|
Process all non-empty substrings of the String s. Note the <= rather than < in the inner loop since we want the second argument to substring to go all the way to the end of the string. |
|
Process all prefixes of the String s. Includes the empty prefix ””. Change initialization of i to i = 1 to exclude the empty prefix. |
|
Process all suffixes of the String s. Includes the empty suffix ””. Change the <= in the condition to < to exclude the empty suffix. |