Topic 3.17: Algorithmic Efficiency | AP CSP Big Idea 3 | APCSExamPrep.com

AP CSP Course Big Idea 3 3.17 Algorithmic Efficiency
3.17
Big Idea 3 • Algorithms & Programming

Algorithmic Efficiency

🕐 ~40 min FREE 📖 6 MCQ questions 🎮 Efficiency Expert game 💻 Live Python editor AAP-4.A

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
📈 Exam weight: Algorithmic efficiency shows up in Big Idea 3 as counting-steps trace items and reasonable-versus-unreasonable classification questions. Knowing that nested loops multiply and that exponential growth is unreasonable earns quick, reliable points.
💡 Think about this first

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.

🎯 What the exam expects

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.

✍ Mini Exercise 1 • Count the steps
A single loop runs and increments 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)
⚠ The multiply-vs-add trap

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.

✍ Mini Exercise 2 • Multiply, do not add
Two loops are nested, each running 4 times. How many steps does 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.

⚠ Faster-growing eventually loses

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.

✍ Mini Exercise 3 • Name the growth
Read the comment. Type the one word (lowercase) the CED uses for time that grows like 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?
this is called:

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.

🎯 Trace it like a machine

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
📋 Create Performance Task • Reasoning about your algorithm

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:

count <- 0 REPEAT n TIMES { REPEAT n TIMES { count <- count + 1 } } DISPLAY(count)

In your written response, describe the algorithm and its iteration honestly:

  • "The outer loop runs once for each of the n items, and for each pass the inner loop also runs n times."
  • "So the algorithm does about n times n steps, 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 →

📈
MCQ Practice
6 questions • Exam difficulty and above • Predict before you peek
Question 1 of 6Trace
Predict first: does the inner loop run n times for each single outer pass?
The counter goes up once per unit of work. What does this code segment display?
n = 6 c = 0 for i in range(n): for j in range(n): c = c + 1 print(c)
Incorrect. 12 is 2 times n, which is what two separate loops would give. These loops are nested, so they multiply.
Correct. The inner loop runs 6 times for each of the 6 outer passes, so c reaches 6 times 6, which is 36.
Incorrect. 6 would be a single loop over n. Here a second loop is nested inside, so it is n times n.
Incorrect. 18 is 3 times n. The nested loops give n times n, which is 36, not a multiple of n.
Question 2 of 6Spot the bug
Predict first: which line does the counting, and how often does it run?
This is meant to count the total number of inner steps, which should be n times n. For n = 5 it prints 5 instead of 25. What is the bug?
n = 5 c = 0 for i in range(n): for j in range(n): pass c = c + 1 print(c)
Correct. The c = c + 1 line sits in the outer loop, so it runs only n times. Moving it inside the inner loop makes it run n times n times.
Incorrect. range(n) already runs n times. Changing it to n + 1 would just miscount; the real issue is where the increment lives.
Incorrect. pass is a valid do-nothing statement. The counting problem is that the increment is outside the inner loop.
Incorrect. The loops are nested, not separate, so they multiply to n times n. The bug is the placement of the increment.
Question 3 of 6NOT question
An algorithm runs in reasonable time when its step count grows like a polynomial. Which growth rate does NOT describe a reasonable-time algorithm?
Incorrect. Growth like n is linear, which is a polynomial, so it is reasonable time.
Incorrect. Growth like n times n is quadratic, which is a polynomial, so it is reasonable time.
Correct. Growth like 2 to the n is exponential, not polynomial, so it is unreasonable time and becomes infeasible fast.
Incorrect. Growth like n cubed is still a polynomial, so it counts as reasonable time even though it grows quickly.
Question 4 of 6I, II, III
Let 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.
Incorrect. I is true, but III is also true: polynomial growth is exactly what reasonable time means.
Correct. I is true (nested loops multiply to n times n) and III is true (polynomial equals reasonable). II is false because separate loops add to 2n, not n times n.
Incorrect. II is false. Separate loops add, giving about 2n steps, not n times n. I is true, so this cannot be the answer.
Incorrect. II is false because separate loops add rather than multiply. Only I and III are true.
Question 5 of 6Spot the bug
Predict first: what value does c hold right after each pass of the loop?
This should count how many times the loop runs, but it prints 1 for every value of n. What is the bug?
c = 0 for i in range(n): c = 0 c = c + 1 print(c)
Correct. The line c = 0 runs every pass, wiping out the total, so c is always just 1 at the end. The reset belongs before the loop, not inside it.
Incorrect. Where range starts does not cause a stuck value of 1. The reset inside the loop is what destroys the count.
Incorrect. Moving print inside would show 1 each time too. The real cause is that c is reset to 0 every pass.
Incorrect. Changing the increment does not help while c is reset to 0 on every pass. Remove the reset from inside the loop.
Question 6 of 6Growth rates
Algorithm P takes about n times n steps. Algorithm Q takes about 500 times n steps. Which statement is true as n grows very large?
Incorrect. For large n, n times n overtakes 500 times n, so P does not always take fewer steps.
Incorrect. Q is smaller only after n passes 500. For small n the constant 500 makes Q larger.
Correct. n times n is below 500 times n while n is under 500, but past 500 the quadratic P grows faster and takes more steps. The faster-growing algorithm eventually loses.
Incorrect. The step counts are equal only at n = 500. For other values one is clearly larger.
🎮 Lesson Game
Efficiency Expert
Count the steps each loop structure takes and predict the total. 8 rounds.
0
Correct
1/8
Round
0
Streak 🔥
🐛 Python • how many steps?
0/8
correct answers
💻 Live Python Code Editor
Practice Problems
Real Python runs right here in your browser. The first time you press Run, the Python engine loads (a few seconds); after that it is instant. Problems build from guided to Create-Task level. Use Hint if you are stuck, and check your output against the target.
Hints used: 0 • Solutions viewed: 0
Level 1 • Guided
Problem 1 of 8 • count a single loop
Count the steps of one loop over n items. Loop n times, add 1 to count each pass, then print count. Target output: 6
Level 2 • Nested loop
Problem 2 of 8 • n times n
Count the steps of a nested loop. Both loops run n times; add 1 to count on every inner pass, then print count. Target output: 25
Level 3 • Separate loops
Problem 3 of 8 • steps add, not multiply
Two separate loops (not nested), each running n times, both adding 1 to the same count. Because they are separate, the steps add. Print count. Target output: 14
Level 4 • Fix the bug
Problem 4 of 8 • put the count in the right place
This should count every inner step of a nested loop (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
Level 5 • Compare
Problem 5 of 8 • linear vs quadratic
For the same 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 n times n)
Target output:
5
25
Level 6 • Create Task style
Problem 6 of 8 • count a search
Measure the work a linear search does. Scan the list from the front, adding 1 to count for each item you compare, and stop as soon as you find target. Print how many comparisons it took. Target output: 3
Level 7 • Challenge
Problem 7 of 8 • you write the whole program
Open ended. Write the entire program yourself. For the given 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 faster if the nested count is larger, otherwise same
Target output:
6
36
quadratic grows faster
Level 8 • Challenge
Problem 8 of 8 • doubling the input
Open ended. Write the entire program yourself. Show that doubling the input roughly quadruples the work for a nested loop:
  • 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 //
Target output:
16
64
4

Frequently Asked Questions

Efficiency measures how the number of steps an algorithm takes grows as the input size n grows. We count steps rather than timing with a clock, because a clock also measures the hardware and other running programs. Counting steps describes the algorithm itself, so the answer is the same on any machine.
Because the inner loop runs all the way through for every single pass of the outer loop. If the outer loop runs n times and the inner loop runs n times, the inner work happens n times n times. Two loops that are side by side rather than nested each run once, so their steps add to about 2n.
Reasonable time means the step count grows like a polynomial, such as n, n squared, or n cubed. Unreasonable time means it grows like an exponential, such as 2 to the n. Exponential growth starts small but explodes, so an unreasonable-time solution becomes infeasible almost immediately as the input grows.
Not necessarily. Efficiency is about the trend as n grows, not one small case. An algorithm that grows faster can win on tiny inputs and still lose badly for large n. For example n squared beats 500 times n while n is under 500, but past that point the quadratic one takes far more steps.
A heuristic is a rule of thumb that produces a good-enough, approximate answer quickly, without guaranteeing the best possible answer. You use one when no efficient exact solution is known, such as finding the shortest route through many cities. It trades a guarantee of perfection for an answer you can compute in reasonable time.
📦
AP CSP Teacher SuperpackSlides, lesson plans, unit tests for all 5 Big Ideas, $249
Get the Superpack →
🏫
For teachers

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.

Typically responds within 24 hours

Message Sent!

Thanks for reaching out. I'll get back to you within 24 hours.

🏫 Welcome, fellow educator!

I offer curriculum resources, practice materials, and study guides designed for AP CS teachers. Let me know what you're looking for — whether it's classroom materials, a guest speaker, or Teachers Pay Teachers resources.

Email

[email protected]

📚

Courses

AP CSA, CSP, & Cybersecurity

Response Time

Within 24 hours

Prefer email? Reach me directly at [email protected]