Topic 3.17: Algorithmic Efficiency | AP CSP Big Idea 3 | APCSExamPrep.com
Algorithmic Efficiency
After this lesson, you will be able to:
- Compare algorithms by counting the number of steps they take as the input grows, not by clock time
- Recognize that a single loop over n items runs in about n steps, which is linear
- Recognize that a nested loop over n items runs in about n times n steps, because nested loops multiply
- Tell reasonable (polynomial) running time apart from unreasonable (exponential) running time
- Explain why an exponential-time solution becomes infeasible as the input grows
- Describe when a heuristic gives a good-enough answer faster than an exact solution
Suppose a program checks every pair of students in a class to find matching birthdays. With 10 students that is about 100 checks. Double the class to 20 and it is not 200 checks, it is about 400. The work grew four times as fast as the class. Now imagine a program that tries every possible combination of choices: at 10 items it is about a thousand steps, but at 60 items it is more steps than a fast computer could finish in a lifetime. This lesson is about predicting how fast an algorithm's work grows, and why some algorithms are usable while others are hopeless.
Efficiency Means Counting Steps, Not Seconds
Algorithmic efficiency is about how the amount of work an algorithm does grows as the size of its input grows. The size of the input is usually called n: the number of items in a list, the number of users, the number of pixels. The key question is not "how many seconds does it take" but "how many steps does it take, and how does that step count change when n gets bigger."
We deliberately count steps instead of timing with a clock. A stopwatch measures the computer, the network, and what else the machine happens to be doing. Counting steps measures the algorithm itself, so the answer is the same on a fast laptop or a slow phone. To make this concrete, every example below uses a count variable that goes up by one each time the algorithm does a unit of work, and then prints the total.
# ONE loop over n items: about n steps (linear) count = 0 for i in range(n): count = count + 1 print(count)
count <- 0 REPEAT n TIMES { count <- count + 1 } DISPLAY(count)
A single loop that runs n times does about n steps. We call this linear growth: double the input and you roughly double the work. If n is 5 the count is 5; if n is 500 the count is 500. Simple and predictable.
The CED (AAP-4.A) asks you to compare algorithms by the number of steps they take relative to the input size. On the exam you will not compute exact runtimes. You will reason about how the step count grows: linear, then squared, then explosively.
count each pass. How many steps does it print?count = 0 for i in range(5): count = count + 1 print(count)
Nested Loops Multiply
Put one loop inside another and the work explodes. For every single pass of the outer loop, the inner loop runs all the way through. So an inner loop of n steps running inside an outer loop of n steps does about n times n steps. This is quadratic growth, often written n squared.
# NESTED loop: about n times n steps (quadratic) count = 0 for i in range(n): for j in range(n): count = count + 1 print(count)
count <- 0 REPEAT n TIMES { REPEAT n TIMES { count <- count + 1 } } DISPLAY(count)
The single most common mistake is thinking nested loops add. They do not. Two loops side by side add (that is n plus n, which is 2n). Two loops nested multiply (that is n times n). Compare the nested version above with two separate loops below, which only reach 2n.
# TWO separate loops: steps ADD, not multiply count = 0 for i in range(n): count = count + 1 for j in range(n): count = count + 1 print(count)
count <- 0 REPEAT n TIMES { count <- count + 1 } REPEAT n TIMES { count <- count + 1 } DISPLAY(count)
Nested loops multiply; separate loops add. And because quadratic grows so fast, doubling the input roughly quadruples the work. If n going from 10 to 20 turns 100 steps into 400 steps, you are looking at n squared. A favorite MCQ hands you a nested loop and offers 2n as a tempting wrong answer.
count reach?count = 0 for i in range(4): for j in range(4): count = count + 1 print(count)
Reasonable Time vs Unreasonable Time
The CED draws one big line. An algorithm runs in reasonable time when its step count grows like a polynomial in n: n, or n squared, or n cubed. These grow, but at a pace we can plan around. An algorithm runs in unreasonable time when its step count grows like an exponential, such as 2 to the n. Exponential growth starts small and then detonates.
Look at the numbers. For 2 to the n: at n = 10 it is about a thousand, at n = 20 about a million, at n = 40 about a trillion, at n = 60 it is more steps than a fast computer could finish in a lifetime. An exponential-time solution becomes infeasible almost immediately as the input grows, even though it may look harmless for tiny inputs. That is why "it works on my small test" is not proof that an algorithm is efficient.
An algorithm that grows faster can still be quicker on tiny inputs and yet lose badly as n grows. Suppose one algorithm takes n squared steps and another takes 500 times n steps. For small n the first is faster, but once n passes 500 the n squared one takes far more steps. Efficiency is about the trend as n grows, not the score on one small case.
2 to the n.# a brute-force search tries every subset # of n items, so its steps grow like 2 ** n # is that reasonable or unreasonable time?
When Exact Is Too Slow: Heuristics
Some problems have no known efficient (reasonable-time) exact solution. Finding the truly shortest route that visits many cities is a classic example: checking every possible order is exponential and hopeless past a few dozen cities. When an exact answer is out of reach, we use a heuristic: a rule of thumb that produces a good-enough answer quickly, without guaranteeing the best possible answer.
A delivery app that always drives to the nearest unvisited stop next is using a heuristic. The route it builds is usually close to optimal and it is computed in reasonable time, which is a trade every real system makes: give up a guarantee of perfection to get an answer you can actually use. On the exam, remember the definition: a heuristic gives an approximate, good-enough solution faster than an exact method, and it is what you reach for when an efficient exact algorithm is not known.
To answer a counting-steps question: find the loops, decide whether they are separate (add) or nested (multiply), and count how many times the innermost work runs. One loop over n is n. A loop inside a loop is n times n. Then classify: polynomial is reasonable, exponential is unreasonable.
Key Vocabulary
| Term | Definition | Example |
|---|---|---|
| Algorithmic efficiency | How the number of steps an algorithm takes grows as the input size n grows | steps vs n, not seconds |
| Linear | Step count grows about like n; one loop over n items | n = 500 gives ~500 steps |
| Quadratic | Step count grows about like n times n; a nested loop | n = 500 gives ~250000 |
| Reasonable time | Step count grows like a polynomial (n, n squared, n cubed) | usable as n grows |
| Unreasonable time | Step count grows like an exponential (2 to the n); infeasible fast | n = 60 is hopeless |
| Heuristic | A rule of thumb giving a good-enough answer quickly, not guaranteed best | go to nearest stop next |
The Create Task written response asks you to describe an algorithm in your program that includes selection and iteration. Understanding efficiency helps you describe that algorithm precisely and choose a structure that actually runs in reasonable time.
A point-earning example
Suppose your program compares every item to every other item, for example to find duplicate entries. That is a nested loop, and you should be able to state how much work it does:
In your written response, describe the algorithm and its iteration honestly:
- "The outer loop runs once for each of the
nitems, and for each pass the inner loop also runsntimes." - "So the algorithm does about
ntimesnsteps, which grows quadratically as the list gets larger." - "This is polynomial growth, so the program still runs in reasonable time for the input sizes it is designed to handle."
The trap to avoid
Do not claim two nested loops do 2n steps. Nested loops multiply, so it is n times n. If a single loop would solve the problem, prefer it: choosing a linear structure over a needless quadratic one is exactly the kind of design decision that shows real understanding. See the full Create Task module →
Get a free AP CSP question every day
Join 3,000+ students. Daily practice, study tips, and exam strategies.
n times n. For n = 5 it prints 5 instead of 25. What is the bug?n be the size of the input. Which of the following statements are true?- I. Two loops nested one inside the other, each running n times, take about n times n steps.
- II. Two separate loops, each running n times, take about n times n steps.
- III. An algorithm whose steps grow like a polynomial runs in reasonable time.
n. What is the bug?n times n steps. Algorithm Q takes about 500 times n steps. Which statement is true as n grows very large?n items. Loop n times, add 1 to count each pass, then print count. Target output: 6
n times; add 1 to count on every inner pass, then print count. Target output: 25
n times, both adding 1 to the same count. Because they are separate, the steps add. Print count. Target output: 14
n times n) and print 16, but the increment is in the wrong loop, so it prints 4. Move the counting line so it prints 16. Target output: 16
n, count a single loop and a nested loop, then print each total on its own line:- first line: the linear count (about
n) - second line: the quadratic count (about
ntimesn)
5
25
count for each item you compare, and stop as soon as you find target. Print how many comparisons it took. Target output: 3
n, measure and report both growth rates:- print the linear step count (a single loop over
n) - print the quadratic step count (a nested loop over
n) - then print
quadratic grows fasterif the nested count is larger, otherwisesame
6
36
quadratic grows faster
- print the nested-loop step count for
n - print the nested-loop step count for
2 * n - print the second count divided by the first using integer division
//
16
64
4
Frequently Asked Questions
🔗 Continue studying
The Superpack includes an editable Topic 3.17 slide deck with animated step-counting traces, a linear-versus-quadratic loop bank, a reasonable-versus-unreasonable sorting worksheet, and a unit quiz. View what's included →
Get in Touch
Whether you're a student, parent, or teacher — I'd love to hear from you.
Just want free AP CS resources?
Enter your email below and check the subscribe box — no message needed. Students get daily practice questions and study tips. Teachers get curriculum resources and teaching strategies.
Message Sent!
Thanks for reaching out. I'll get back to you within 24 hours.
Prefer email? Reach me directly at [email protected]