Java: counting operations to see growth rates
Count loop iterations instead of timing them to compare linear, quadratic, and logarithmic growth.
class Main {
static long[] count(int n) {
long linear = 0, quadratic = 0, logarithmic = 0;
for (int i = 0; i < n; i++) {
linear++;
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
quadratic++;
}
}
for (int k = n; k > 1; k /= 2) {
logarithmic++;
}
return new long[] {linear, quadratic, logarithmic};
}
public static void main(String[] args) {
for (int n : new int[] {8, 16, 32}) {
long[] c = count(n);
System.out.println("n=" + n + " linear=" + c[0] + " quadratic=" + c[1] + " log=" + c[2]);
}
}
}n=8 linear=8 quadratic=64 log=3 n=16 linear=16 quadratic=256 log=4 n=32 linear=32 quadratic=1024 log=5
Explanation
Analysis of algorithms asks how the work grows as the input size n grows. Timing a program mixes in the machine, the JVM warm-up, and the garbage collector, so a clean way to see growth is to count the basic steps directly.
A single loop over n items does about n steps, two nested loops over n items do about n squared steps, and a loop that halves its counter does about log2(n) steps. Doubling n doubles the first, quadruples the second, and adds only one step to the third.
Explore the dry run
class Main { static long[] count(int n) { long linear = 0, quadratic = 0, logarithmic = 0; for (int i = 0; i < n; i++) { linear++; } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { quadratic++; } } for (int k = n; k > 1; k /= 2) { logarithmic++; } return new long[] {linear, quadratic, logarithmic}; } public static void main(String[] args) { for (int n : new int[] {8, 16, 32}) { long[] c = count(n); System.out.println("n=" + n + " linear=" + c[0] + " quadratic=" + c[1] + " log=" + c[2]); } }}Follow the example
Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.
View the complete dry-run table
| Step / line | What happens | State after step | Output so far |
|---|---|---|---|
| The first loop adds one for each of the n iterations. | n = 8, linear = 8 | — | |
| The inner statement runs n times for each of the n outer passes. | n = 8, quadratic = 64 | — | |
| k goes 8, 4, 2, then stops at 1, so there are three halvings. | k = 8 → 4 → 2 → 1, log = 3 | — | |
| Print one row per size. Each time n doubles, linear doubles, quadratic quadruples, and log grows by one. | k = 8 → 4 → 2 → 1, log = 3 | n=8 linear=8 quadratic=64 log=3 n=16 linear=16 quadratic=256 log=4 n=32 linear=32 quadratic=1024 log=5 |
Cost and common mistakes
The three loops take Θ(n), Θ(n²), and Θ(log n) time with O(1) extra space.
- Counting steps measures growth, not seconds. Constant factors, caching, and the JIT compiler still affect real running time.
- An int counter would overflow for large quadratic counts; the example uses long.
Try it yourself
Predict the three counts for n = 64.
Reveal answer and reasoning
linear = 64, quadratic = 4096, and log = 6, because 64 halves six times to reach 1.