Recursion - Building the printArray() Assignment

A 60-minute assignment-completion lesson in 62 slides. It defines a recursive method as a base case plus a recursive step, traces printArray by hand on a three-element array so you can watch the call stack grow and unwind, and then scaffolds the graded assignment in eight steps: a 100-element array filled by a for loop with rand.nextInt(100) + 1 and printed space-separated by a recursive printArray. Five traps cover the crashes that actually happen - deleting the base case and hitting ArrayIndexOutOfBoundsException, stopping one element early, expecting nextInt(100) to include 100 when it returns 0 through 99, using println and printing a column instead of a row, and forgetting the + 1, which produces a StackOverflowError past a thousand frames. The deck ends with a section on screenshots and submission, on the principle that you only get credit for what you demonstrate, and two extensions that prove you own the material: printing backwards by swapping two lines, and writing a recursive sum. Every snippet, output, error message, and stack trace was compiled and executed under OpenJDK Temurin 21.0.11.

Subject: Java · 103 slides · code lesson

Open the interactive version of this deck · Homework for this lesson

What this lesson covers

The lesson, slide by slide

1. Recursion in Java - Building printArray()

Title

2. What you will be able to do

Objectives

So far, your programs have been methods calling other methods. Today a method calls itself - and by the end of the hour, your graded assignment is finished and screenshotted.

1. Say what a recursive method is, and point to its two required parts: the base case and the recursive step.

2. Trace a recursive printArray on a 3-element array by hand, drawing the call stack as it grows and unwinds.

3. Build the full assignment: a 100-element array, filled by a for loop with random numbers from 1 to 100 inclusive, printed space-separated by a recursive printArray().

4. Predict and recognize the two classic recursion crashes: ArrayIndexOutOfBoundsException and StackOverflowError.

5. Capture the screenshots the grader requires - and prove you own the idea by printing the array backwards with a 2-line change.

3. The assignment, decoded

Concept

Before writing anything, translate each sentence of the assignment into the code it is really asking for.

the assignment sayswhich means
Write a recursive method printArray()A method that calls itself - no loop inside it
Displays all the elements, separated by spacesSystem.out.print(... + " ") - print, not println
The array must be 100 elements in sizeint[] array = new int[100];
Filled using a for loop and a random number generatorA normal for loop + java.util.Random
Random number between 1 and 100 inclusiverand.nextInt(100) + 1
Screenshots show your program runningPlan the capture before the session ends

Notice: only one method has to be recursive. The filling loop is a plain for loop you already know - the assignment says so explicitly.

4. Fill in: which means for The assignment, decoded

Comparison

Comparison matrix

From The assignment, decoded: refill the which means column from what you know. The rest of the table is as it appeared.

the assignment sayswhich means
Write a recursive method printArray()A method that calls itself - no loop inside it
Displays all the elements, separated by spacesSystem.out.print(... + " ") - print, not println
The array must be 100 elements in sizeint[] array = new int[100];
Filled using a for loop and a random number generatorA normal for loop + java.util.Random
Random number between 1 and 100 inclusiverand.nextInt(100) + 1
Screenshots show your program runningPlan the capture before the session ends

5. How we will spend the hour

Concept

minuteswhat we do
0-10What recursion is: base case + recursive step
10-20Trace a tiny example by hand - the highest-value 10 minutes
20-45Build the assignment, step by step, in your editor
45-52Run it and capture the required screenshots
52-60Prove you own it: print backwards, preview recursive sum

The screenshots are the grade, so they are scheduled inside the hour - not left for later.

6. What each one costs: How we will spend the hour

Trade off

Comparison matrix

From How we will spend the hour: every row here is a choice with a cost. Fill the what we do column, then say which row you would actually pick and what you give up for it.

minuteswhat we do
0-10What recursion is: base case + recursive step
10-20Trace a tiny example by hand - the highest-value 10 minutes
20-45Build the assignment, step by step, in your editor
45-52Run it and capture the required screenshots
52-60Prove you own it: print backwards, preview recursive sum

7. Part 1 · What Is Recursion?

Section

8. The loop version you already know

Concept

How would you print every element of an array with a loop? You could write this in your sleep:

for (int i = 0; i < array.length; i++) {
    System.out.print(array[i] + " ");
}

On the array {7, 2, 9} the loop does three passes and stops when i reaches 3:

passiprints
107
212
329
-3loop condition false - stop

Keep this trace in your head. Recursion will do the exact same four things - just without a loop.

9. Break it if you can: The loop version you already know

Counterexample

Discussion prompt

How would you print every element of an array with a loop? You could write this in your sleep:

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

Answer:

On the array {7, 2, 9} the loop does three passes and stops when i reaches 3:

10. Counting off: recursion with people

Intuition

Imagine a line of people who need to count off. Nobody runs a loop. Each person follows one tiny rule: say your number, then tap the next person.

The last person has a different rule: if there is nobody behind you, stop. Without that person, the tapping would never end.

That is all recursion is: everyone runs the same rule, each on a slightly smaller remaining line, and one special case stops the chain.

11. By analogy: Counting off: recursion with people

Analogy

Discussion prompt

Explain Counting off: recursion with people by analogy to something with no Java in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

Imagine a line of people who need to count off. Nobody runs a loop. Each person follows one tiny rule: say your number, then tap the next person.

12. A method that calls itself

Concept

A recursive method is a method that calls itself - directly, or indirectly through another method. Each call handles one small piece and hands the rest to a fresh call of the same method.

callhandleshands off
printArray(arr, 0)element 0the rest, starting at 1
printArray(arr, 1)element 1the rest, starting at 2
printArray(arr, 2)element 2the rest, starting at 3
printArray(arr, 3)nothing leftnobody - it stops

"Print the array starting at index 0" becomes: print element 0, then print the array starting at index 1. Same job, smaller problem.

13. Teach it back: A method that calls itself

Explain it

Discussion prompt

Explain A method that calls itself to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

A recursive method is a method that calls itself - directly, or indirectly through another method. Each call handles one small piece and hands the rest to a fresh call of the same method.

14. Two words to own

Concept

Base case — The condition under which the method does NOT call itself - it just stops (returns). For printArray: the index has walked past the last element.

Recursive step — The line where the method calls itself on a smaller version of the problem. For printArray: print one element, then call yourself with index + 1.

Every recursive method you will ever write has both. Missing base case: it never stops. A recursive step that does not shrink the problem: it never stops. We will crash both ways today - on purpose.

15. Take the definitions apart: Base case vs Recursive step

Definition probe

Sort into buckets

Every line below is part of the definition of Base case or of Recursive step — one or the other, never both. Put each where it belongs.

Base case
The condition under which the method does NOT call itself - it just stops (returns).; the index has walked past the last element.
Recursive step
The line where the method calls itself on a smaller version of the problem.; print one element, then call yourself with index + 1.
b1
The condition under which the method does NOT call itself - it just stops (returns). For printArray: the index has walked past the last element.
b2
The line where the method calls itself on a smaller version of the problem. For printArray: print one element, then call yourself with index + 1.

16. The recursion skeleton

Pattern

Memorize this shape. Every recursive method today (and most you will ever write) is this skeleton with the blanks filled in:

static void doJob(int[] array, int index) {
    if (index == array.length) {   // 1. base case: STOP
        return;
    }
    // 2. do ONE small piece of work here
    doJob(array, index + 1);       // 3. recursive step: the REST
}
piecejob
if (index == array.length)base case - detects there is nothing left to do
return;stops this call without calling again
the work linehandles exactly one element
doJob(array, index + 1)same method, smaller problem
+ 1the shrinking - without it, the problem never gets smaller

Order matters: check the base case first, then work, then recurse. We always write the base case before anything else.

17. Where does it stop working: The recursion skeleton

Edge cases

Discussion prompt

The recursion skeleton works on the cases you have just seen. Push it to the edge: what is the most degenerate input it still handles — empty, zero, one item, everything equal — and what is the first case where it stops being true? Name the case, not just "it breaks".

Hint: Try the smallest legal input, then the largest, then the one where two things collide. Methods are specified at their edges; the middle takes care of itself.

Answer:

Memorize this shape. Every recursive method today (and most you will ever write) is this skeleton with the blanks filled in:

18. Why the problem must shrink

Intuition

Each recursive call must be given a strictly smaller problem than the one it received - here, an index one closer to the end.

Shrinking problem + a base case waiting at the bottom = guaranteed to finish. It is the same promise a for loop makes with i++ and its stopping condition - just written as a method.

When a recursive method misbehaves, ask exactly two questions: Is there a base case? Does every call move toward it? One of the two answers is always no.

19. Trap: delete the base case

Trap

The trap

"The recursion will just stop on its own when the array runs out, right?" Let's delete the base case and find out:

static void printArray(int[] array, int index) {
    System.out.print(array[index] + " ");
    printArray(array, index + 1);   // no base case!
}

The fix

On {7, 2, 9} it prints 7 2 9 - and then the fourth call executes array[3] on a 3-element array. Compiled and run, it crashes with exactly this:

what the real run printedwhy
7 2 9the first three calls worked fine
ArrayIndexOutOfBoundsException: Index 3 out of bounds for length 3call number 4 read past the end of the array
at NoBaseCase.printArray(NoBaseCase.java:4)the crash is on the array-read line, not the recursive call

The base case if (index == array.length) return; exists to fire before array[index] runs. It is the bouncer at the door - remove it and the very next call walks off the end.

20. Rule out three: Check: the job of the base case

Elimination

Eliminate the wrong options

In printArray, what is the job of the line if (index == array.length) { return; }?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. It prints the last element of the array.
  • B. It restarts the recursion from index 0.
  • C. It stops the recursion once the index has walked past the last element.
  • D. It removes the element at position index from the array.

Survives elimination: C

Why: That line is the base case. Valid indexes run from 0 to array.length - 1, so the moment index equals array.length there is nothing left to print, and returning without another recursive call stops the whole chain.

21. Check: the job of the base case

Check

Check your understanding

In printArray, what is the job of the line if (index == array.length) { return; }?

  • A. It prints the last element of the array.
  • B. It restarts the recursion from index 0.
  • C. It stops the recursion once the index has walked past the last element. (correct)
  • D. It removes the element at position index from the array.

Answer: C

Why: That line is the base case. Valid indexes run from 0 to array.length - 1, so the moment index equals array.length there is nothing left to print, and returning without another recursive call stops the whole chain.

Why A tempts people
It prints nothing - it returns before the print line is ever reached. The last element was printed by the previous call, at index array.length - 1.
Why B tempts people
Nothing in the method sets index back to 0. Each call only ever moves the index forward by one.
Why D tempts people
Java arrays have a fixed size and nothing here modifies the array. The method only reads elements.

22. Part 2 · Trace It by Hand

Section

23. Guess the shape of the answer: Our tiny test array

Estimation

Predict first

Never trace recursion for the first time on 100 elements. We shrink the problem to 3 elements, trace it perfectly, and then trust the same mechanism at 100.

Commit before you compute: what does Our tiny test array come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.

Correct: Name what we know before running anything

Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. arr.length is 3, valid indexes are 0, 1, 2, and the first call starts the index at 0.

24. Our tiny test array

Worked example

Never trace recursion for the first time on 100 elements. We shrink the problem to 3 elements, trace it perfectly, and then trust the same mechanism at 100.

int[] arr = {7, 2, 9};
printArray(arr, 0);   // expected output: 7 2 9

Name what we know before running anything

Why: arr.length is 3, valid indexes are 0, 1, 2, and the first call starts the index at 0.

indexvalue
07
12
29

Predict before you trace: how many calls to printArray will happen in total? Lock in a number - the trace will confirm or correct it.

25. Watch it run: Our tiny test array

Pattern

Step through it

Step through Our tiny test array one row at a time. What is driving the change, and what would the row after the last one be?

  1. Step 1: index is 0
  2. Step 2: index is 1
  3. Step 3: index is 2

26. What has to happen first: Call 1: printArray(arr, 0)

Ranking

Put in order

Put the moves of Call 1: printArray(arr, 0) into the order they have to happen.

  1. Check the base case: is 0 == 3?
  2. Print one element: arr[0] is 7
  3. Hand off the rest: printArray(arr, 1)

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. No - so we do NOT stop. We fall through to the work line.

27. Call 1: printArray(arr, 0)

Worked example

static void printArray(int[] array, int index) {
    if (index == array.length) {
        return;
    }
    System.out.print(array[index] + " ");
    printArray(array, index + 1);
}

Check the base case: is 0 == 3?

Why: No - so we do NOT stop. We fall through to the work line.

questionanswer
index == array.length?0 == 3 is false - keep going
work line prints7 (that is arr[0])
then callsprintArray(arr, 1)

Print one element: arr[0] is 7

Why: Each call handles exactly one element - this call's element is the one at its own index.

Hand off the rest: printArray(arr, 1)

Why: Call 1 is now PAUSED on line 6, waiting for the hand-off to finish. It has not returned yet.

28. Inspect it line by line: Call 1: printArray(arr, 0)

Error analysis

Annotate

Walk the callouts on Call 1: printArray(arr, 0). Each one is a place this is easy to get subtly wrong.

  • No - so we do NOT stop. We fall through to the work line.
  • Each call handles exactly one element - this call's element is the one at its own index.
  • Call 1 is now PAUSED on line 6, waiting for the hand-off to finish. It has not returned yet.

29. What has to be given first: Calls 2 and 3 ride the same rails

Missing information

Discussion prompt

Three calls are now paused, each waiting on the one it started. The output so far reads 7 2 9 - and one more call is in flight.

What do you need to know — or decide — before the first line can be written? List everything the problem has to hand you.

Hint: Anything you would have to invent to get started is a thing the problem must supply.

Answer:

1 == 3 is false, prints arr[1] which is 2, then calls printArray(arr, 2) and pauses.

30. Calls 2 and 3 ride the same rails

Worked example

Call 2: printArray(arr, 1)

Why: 1 == 3 is false, prints arr[1] which is 2, then calls printArray(arr, 2) and pauses.

Call 3: printArray(arr, 2)

Why: 2 == 3 is false, prints arr[2] which is 9, then calls printArray(arr, 3) and pauses.

callbase case?printsthen calls
printArray(arr, 0)0 == 3? no7printArray(arr, 1)
printArray(arr, 1)1 == 3? no2printArray(arr, 2)
printArray(arr, 2)2 == 3? no9printArray(arr, 3)

Three calls are now paused, each waiting on the one it started. The output so far reads 7 2 9 - and one more call is in flight.

31. Work backwards from the answer: Calls 2 and 3 ride the same rails

Reverse engineer

Discussion prompt

Work backwards. The example finished here:

Call 3: printArray(arr, 2)

What was it asked to do, and what must it have been given? Reconstruct the problem from its answer.

Hint: Every quantity in the result had to enter somewhere. Account for each one.

Answer:

Three calls are now paused, each waiting on the one it started. The output so far reads 7 2 9 - and one more call is in flight.

32. Call 4: the base case fires

Concept

Call 4 is printArray(arr, 3). This time the base-case check asks: is 3 == 3? Yes. The method returns immediately - it prints nothing and starts no new call.

callbase case?prints
printArray(arr, 3)3 == 3? YESnothing - just return

So the answer to the prediction: 4 calls for 3 elements. Always one extra - the quiet call whose only job is to say "we're done."

33. The call stack, growing

Concept

Java keeps track of the paused calls on the call stack. Every call gets a frame; the frame stays until that call returns. At the deepest moment, our stack looks like this:

stack (top = most recent)state
printArray(arr, 3)checking base case - about to return
printArray(arr, 2)paused: printed 9, waiting
printArray(arr, 1)paused: printed 2, waiting
printArray(arr, 0)paused: printed 7, waiting
mainpaused: waiting for printArray(arr, 0)

For the real assignment this tower is 101 printArray frames tall. Same picture, taller stack - Java handles thousands of frames without complaint.

34. The call stack, unwinding

Concept

Now the returns cascade. Call 4 returns to call 3. Call 3 has nothing left after its recursive call, so it returns to call 2 - and so on down the tower.

stepwhat returnsstack height after
1printArray(arr, 3) finishes3 printArray frames
2printArray(arr, 2) finishes2 printArray frames
3printArray(arr, 1) finishes1 printArray frame
4printArray(arr, 0) finishes0 - we are back in main

Nothing prints during the unwind because the recursive call is the last line of the method. File that away - it becomes interesting in Part 6 when we move a line and the unwind starts printing.

35. Same four things as the loop

Intuition

Put the recursion trace next to the loop trace from Part 1. They are the same movie:

momentthe loop didthe recursion did
handle element 0pass 1: i = 0, prints 7call 1: index 0, prints 7
handle element 1pass 2: i = 1, prints 2call 2: index 1, prints 2
handle element 2pass 3: i = 2, prints 9call 3: index 2, prints 9
notice we are donei = 3: condition false, exitcall 4: base case, return

The loop's i++ became index + 1; the loop's condition became the base case. Recursion is not a new kind of repetition - it is the same repetition, carried by method calls instead of a loop header.

36. Answer it before you see the options: Check: counting the calls

Prediction

Predict first

printArray(arr, 0) runs on the 3-element array {7, 2, 9}. How many times is printArray called in total, counting the first call?

Answer it in your own words, now, with nothing to choose from. The options are on the next slide — and picking the right one off a list is an easier skill than producing it.

Correct: 4 - one per element, plus the base-case call that prints nothing.

Why: Calls at indexes 0, 1 and 2 each print an element, and the fourth call at index 3 hits the base case and returns silently. An n-element array always costs exactly n + 1 calls - the assignment's 100-element array makes 101.

37. Check: counting the calls

Check

Check your understanding

printArray(arr, 0) runs on the 3-element array {7, 2, 9}. How many times is printArray called in total, counting the first call?

  • A. 3 - one call per element.
  • B. 4 - one per element, plus the base-case call that prints nothing. (correct)
  • C. 9 - one call per element value.
  • D. 1 - it is one method, so it is called once.

Answer: B

Why: Calls at indexes 0, 1 and 2 each print an element, and the fourth call at index 3 hits the base case and returns silently. An n-element array always costs exactly n + 1 calls - the assignment's 100-element array makes 101.

Why A tempts people
Close - but the call at index 3 is still a real method call, even though it prints nothing. Without it, nothing would ever stop the chain.
Why C tempts people
The element VALUES (7, 2, 9) never control how many calls happen - only the array LENGTH does. Values are what gets printed, not how far we recurse.
Why D tempts people
Each recursive invocation is a genuine separate call with its own stack frame and its own copy of index. That is exactly why the call stack grows.

38. Trap: stopping one element early

Trap

The trap

"Stop AT the last element" sounds right - so this base case is tempting:

if (index == array.length - 1) {   // stop at the last one?
    return;
}
System.out.print(array[index] + " ");
printArray(array, index + 1);

The fix

Compiled and run on {7, 2, 9}, this prints 7 2 - the 9 silently vanishes. The call at index 2 returns before printing, but index 2 still had work to do.

callwith length - 1should be
printArray(arr, 0)prints 7prints 7
printArray(arr, 1)prints 2prints 2
printArray(arr, 2)2 == 2, returns - prints NOTHINGprints 9

The base case marks the first index with no work left - and index array.length - 1 still has one element to print. Stop at array.length, one past the end. No crash, no error message - just a quietly wrong answer, which is why you must count the output, not just admire it.

39. Check: predict the early stop

Check

Check your understanding

With the base case written as if (index == array.length - 1) return;, what does printArray(arr, 0) output on the array {7, 2, 9}?

  • A. 7 2 9
  • B. 7 2 (correct)
  • C. 2 9
  • D. It crashes with ArrayIndexOutOfBoundsException.

Answer: B

Why: The call at index 2 sees 2 == 3 - 1 and returns before reaching the print line, so the last element is silently skipped. The verified run prints exactly '7 2'. Off-by-one base cases do not crash - they quietly drop an element.

Why A tempts people
That is what the CORRECT base case (index == array.length) prints. The early version returns one call too soon to print the 9.
Why C tempts people
The recursion always starts at index 0 and moves forward, so the FRONT of the array is never skipped - it is the last element that gets lost.
Why D tempts people
No index ever exceeds the array bounds here - the method stops too EARLY, not too late. This bug produces wrong output, not a crash, which makes it more dangerous.

40. Part 3 · Build the Assignment

Section

41. The build plan: eight small steps

Concept

From here on, you type, I prompt. We build in eight steps, and after every step the file still compiles. If we get lost, we recompile and look.

stepwhat gets writtenpart of the assignment
1class + empty mainscaffolding
2the 100-element array'must be 100 elements in size'
3Random + the fill loop'filled using a for loop and a random number generator'
4-7the recursive printArray'write a recursive method printArray()'
8call it from main, run it'displays all the elements'

Steps 2 and 3 are material you already know - we do them first to bank a quick win before the new idea.

42. Step 1 · Class skeleton and main

Worked example

import java.util.Random;

public class PrintArrayRecursion {

    public static void main(String[] args) {
        // everything starts here
    }
}

Import Random at the very top

Why: java.util.Random is not auto-imported; forgetting this line is the most common first compile error today.

linepurpose
import java.util.Random;makes the Random class usable by its short name
public class PrintArrayRecursionclass name must match the file name exactly
public static void main(...)where Java starts running

Compile now, before writing more

Why: A file that compiles every step means any new error was caused by the last five lines you typed - nothing else.

43. Draw the shape of it: Step 1 · Class skeleton and main

Blank canvas

Draw it

Draw what Step 1 · Class skeleton and main just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.

44. Guess the shape of the answer: Step 2 · Instantiate the 100-element array

Estimation

Predict first

Indexes 0 to 99 - not 1 to 100. This same one-past-the-end boundary is exactly where the recursive base case will stand guard later: at index 100.

Commit before you compute: what does Step 2 · Instantiate the 100-element array come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.

Correct: Read the line right to left

Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. new int[100] builds a block of 100 int slots, all starting at 0; int[] array names it.

45. Step 2 · Instantiate the 100-element array

Worked example

int[] array = new int[100];

Read the line right to left

Why: new int[100] builds a block of 100 int slots, all starting at 0; int[] array names it.

factvalue
array.length100 - fixed forever
valid indexes0 through 99
every slot right now0 (Java's default for int)

Indexes 0 to 99 - not 1 to 100. This same one-past-the-end boundary is exactly where the recursive base case will stand guard later: at index 100.

46. Where does each piece belong: Recursion - Building the printArray()…

Sorting

Sort into buckets

These are the pieces of Recursion - Building the printArray() Assignment, out of order. Put each one back under the part of the lesson it belongs to.

Part 1 · What Is Recursion?
The loop version you already know; Counting off: recursion with people; A method that calls itself
Part 2 · Trace It by Hand
Our tiny test array; Call 1: printArray(arr, 0); Calls 2 and 3 ride the same rails
Part 3 · Build the Assignment
The build plan: eight small steps; Step 1 · Class skeleton and main; Step 2 · Instantiate the 100-element array
s1
Part 1 · What Is Recursion? is where Recursion - Building the printArray() Assignment puts The loop version you already know, Counting off: recursion with people, A method that calls itself. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s2
Part 2 · Trace It by Hand is where Recursion - Building the printArray() Assignment puts Our tiny test array, Call 1: printArray(arr, 0), Calls 2 and 3 ride the same rails. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.
s3
Part 3 · Build the Assignment is where Recursion - Building the printArray() Assignment puts The build plan: eight small steps, Step 1 · Class skeleton and main, Step 2 · Instantiate the 100-element array. Knowing which part of the lesson a problem belongs to is most of knowing which method to reach for.

47. Meet java.util.Random

Concept

One Random object serves the whole program. Ask it for numbers with nextInt(n) - which hands back a value from 0 to n - 1, never n itself.

Random rand = new Random();
int roll = rand.nextInt(100);   // 0..99  - note: NOT 1..100
expressionrange it produces
rand.nextInt(100)0 to 99
rand.nextInt(100) + 11 to 100 - what the assignment wants
rand.nextInt(101)0 to 100 - zero is not allowed here
rand.nextInt(6) + 11 to 6 - a die, same recipe

The recipe for "a to b inclusive" is always rand.nextInt(b - a + 1) + a. Today: rand.nextInt(100) + 1.

48. What has to happen first: Step 3 · Fill the array

Ranking

Put in order

Put the moves of Step 3 · Fill the array into the order they have to happen.

  1. Create Random once, OUTSIDE the loop
  2. Loop i from 0 while i < array.length
  3. Store nextInt(100) + 1 each pass

Why: These are the moves of the worked example in the order it makes them, and each one is set up by the one before it. One generator is reused for all 100 numbers - creating it inside the loop works but is wasteful and a bad habit.

49. Step 3 · Fill the array

Worked example

Random rand = new Random();
for (int i = 0; i < array.length; i++) {
    array[i] = rand.nextInt(100) + 1;   // 1..100 inclusive
}

Create Random once, OUTSIDE the loop

Why: One generator is reused for all 100 numbers - creating it inside the loop works but is wasteful and a bad habit.

Loop i from 0 while i < array.length

Why: The standard fill pattern touches indexes 0 through 99 - exactly the valid ones.

Store nextInt(100) + 1 each pass

Why: Verified run: first slots received 65, 41, 38 - every value landed inside 1..100.

passistored (verified run)
1065
2141
3238
......... 100 values total, all in 1..100

50. Fill in: i for Step 3 · Fill the array

Comparison

Comparison matrix

From Step 3 · Fill the array: refill the i column from what you know. The rest of the table is as it appeared.

passistored (verified run)
1065
2141
3238
......... 100 values total, all in 1..100

51. Trap: nextInt(100) is 0 to 99

Trap

The trap

The assignment says 1 to 100 inclusive, and 100 is right there in the call - so this looks done:

array[i] = rand.nextInt(100);   // "between 1 and 100"... right?

The fix

nextInt(100) produces 0 to 99. Sooner or later a 0 lands in the output - and a screenshot with a 0 in it is documented proof the requirement was missed.

versionrangeverdict
rand.nextInt(100)0 to 990 is possible, 100 is impossible - both wrong
rand.nextInt(100) + 11 to 100matches the assignment exactly
rand.nextInt(101)0 to 100still lets 0 through

The bound in nextInt(n) is exclusive: n values starting at 0. Shift the whole window up with + 1 and the range becomes 1 to 100.

52. Break it on purpose: nextInt(100) is 0 to 99

Break the constraint

Discussion prompt

The rule this trap just fixed:

The bound in nextInt(n) is exclusive: n values starting at 0. Shift the whole window up with + 1 and the range becomes 1 to 100.

Now break it on purpose. Build a case that violates it and follow the consequences until something visibly fails. Where does the failure first show up — and would you have noticed it if you had not been looking?

Hint: The dangerous rules are the ones whose violation still produces an answer. If yours fails loudly, try to find one that fails quietly.

53. How sure are you: Check: 1 to 100 inclusive

Commit first

Predict first

Which expression produces a random integer between 1 and 100 inclusive, as the assignment requires?

Commit to an answer, then rate it — certain, fairly sure, or guessing — and write the rating down before you turn the page.

Correct: rand.nextInt(100) + 1

Why: nextInt(100) yields 0 through 99 - one hundred values starting at zero. Adding 1 shifts the whole window to 1 through 100, hitting both endpoints the assignment demands and nothing outside them.

The rating matters as much as the answer: confident-and-wrong is the combination that survives revision, because nothing about it feels like it needs revisiting.

54. Check: 1 to 100 inclusive

Check

Check your understanding

Which expression produces a random integer between 1 and 100 inclusive, as the assignment requires?

  • A. rand.nextInt(100)
  • B. rand.nextInt(101)
  • C. rand.nextInt(100) + 1 (correct)
  • D. rand.nextInt(99) + 1

Answer: C

Why: nextInt(100) yields 0 through 99 - one hundred values starting at zero. Adding 1 shifts the whole window to 1 through 100, hitting both endpoints the assignment demands and nothing outside them.

Why A tempts people
Gives 0 to 99: it can produce a forbidden 0 and can never produce 100. Two separate violations in one call.
Why B tempts people
Gives 0 to 100 - the top end is now right, but 0 can still appear in your screenshot.
Why D tempts people
Gives 1 to 99: no zeros, but 100 itself can never be generated, and the assignment says 100 inclusive.

55. Step 4 · The recursive method's signature

Worked example

Below main, start the star of the show. It needs the array AND a way to know which element is mine - that is the index parameter:

public static void printArray(int[] array, int index) {
    // base case first - next step
}
parameterwhy it must be there
int[] arrayevery call needs to see the same array
int indexeach call's private marker: which element THIS call handles
(return type void)the job is printing, not computing a value

The pseudo-code shows one argument - printArray(integer array). We will honor that exactly in Step 7 with a one-line trick. The index parameter is what makes the recursion possible at all.

56. Step 5 · Base case first, always

Worked example

public static void printArray(int[] array, int index) {
    if (index == array.length) {   // past the last element?
        return;                    // then we are done - stop
    }
}

Write the stop before the go

Why: A recursive method without its base case is a crash waiting to happen - Part 1 proved it with a real ArrayIndexOutOfBoundsException. Writing it first makes the crash impossible.

index arrivingbase case says
0 through 99not yet - there is work to do
100100 == array.length: stop, print nothing

Compare with ==, stop at exactly array.length

Why: Part 2's trap showed length - 1 silently eats the last element. The first index with NO work left is length itself.

57. Predict the next row: Step 6 · Do one small piece of work

Pattern

Predict first

The table runs: System.out.print(array[index] + " ") | 65 41 38 ... - one row, space-separated · System.out.println(array[index]) | one number per line - 100 rows

In Step 6 · Do one small piece of work, given the rows so far: what is the next one — the row where choice is System.out.print(array[index])?

Correct: System.out.print(array[index]) | 654138... - unreadable digit soup

choiceoutput shape
System.out.print(array[index] + " ")65 41 38 ... - one row, space-separated
System.out.println(array[index])one number per line - 100 rows
System.out.print(array[index])654138... - unreadable digit soup

Why: The relationship between the columns, not the individual numbers, is what generates the next row. The assignment says separated by SPACES - println would put every element on its own line.

58. Step 6 · Do one small piece of work

Worked example

public static void printArray(int[] array, int index) {
    if (index == array.length) {
        return;
    }
    System.out.print(array[index] + " ");   // MY one element
}

print, not println

Why: The assignment says separated by SPACES - println would put every element on its own line.

Glue the space on with + " "

Why: Each element prints as the number followed by one space: 65 41 38 ... on a single line.

choiceoutput shape
System.out.print(array[index] + " ")65 41 38 ... - one row, space-separated
System.out.println(array[index])one number per line - 100 rows
System.out.print(array[index])654138... - unreadable digit soup

59. Trap: println prints a column, not a row

Trap

The trap

println is the habit your fingers know, and the program even looks like it works:

System.out.println(array[index]);   // one element per LINE

The fix

One hundred numbers, one per line, scrolls the console for pages - and the assignment's phrase separated by spaces is not what the screenshot shows.

methodwhen to use it
print(x + " ")building a row piece by piece - today's job
println(x)when each item deserves its own line
println() with nothingfinishing a row: one clean newline at the end

Polish: after the whole recursion finishes back in main, one bare System.out.println(); ends the row so the command prompt does not glue itself to your 100th number in the screenshot.

60. Step 7 · The recursive call - and the pseudo-code's one argument

Worked example

// Matches the pseudo-code: printArray(integer array)
public static void printArray(int[] array) {
    printArray(array, 0);   // hand off to the worker, starting at 0
}

public static void printArray(int[] array, int index) {
    if (index == array.length) {
        return;
    }
    System.out.print(array[index] + " ");
    printArray(array, index + 1);   // the recursive step
}

Add the recursive call with index + 1

Why: One element handled, the rest handed to a fresh call one step closer to the base case. This line is what makes the method recursive.

Add the one-argument version the pseudo-code shows

Why: Two methods, same name, different parameter lists - an OVERLOAD. The short one just starts the real one at index 0, so main can call printArray(array) exactly like the assignment's pseudo-code.

call writtenwhich version runs
printArray(array)the 1-arg starter - which immediately calls the worker
printArray(array, 0)the 2-arg recursive worker, from the top
printArray(array, index + 1)the 2-arg worker again - one element further along

61. Trap: forgetting the + 1

Trap

The trap

One missing character - passing index instead of index + 1 - and the method still compiles perfectly:

System.out.print(array[index] + " ");
printArray(array, index);   // forgot the + 1

The fix

Every call now hands off the same problem it received. Nothing ever moves toward the base case. The real run printed 7 7 7 7 7 ... and then died - with over a thousand identical stack frames:

what the real run showedmeaning
7 7 7 7 7 7 ...index stays 0 forever - same element every call
java.lang.StackOverflowErrorthe call stack ran out of room for new frames
at NoProgress.printArray(NoProgress.java:8) x 1000+the same line, over a thousand times - the loop that never shrank

This is the second recursion crash: the base case exists, but no call ever reaches it. Diagnosis rule - repeated output + StackOverflowError = the problem is not shrinking. Check the recursive call's arguments.

62. Which of these survive contact with Recursion - Building the printArray()…?

Two truths and a lie

Sort into buckets

Some of these hold up and some are the exact mistakes this lesson is built to prevent. Sort them.

Holds up
Before writing anything, translate each sentence of the assignment into the code it is really asking for.; How would you print every element of an array with a loop? You could write this in your sleep:; Imagine a line of people who need to count off. Nobody runs a loop. Each person follows one tiny rule: say your number, then tap the next person.
Breaks
"The recursion will just stop on its own when the array runs out, right?" Let's delete the base case and find out:; "Stop AT the last element" sounds right - so this base case is tempting:
sound
These are stated as this lesson states them — each one survives the edge cases Recursion - Building the printArray() Assignment puts it through.
flawed
Each of these is lifted from a trap in this deck: reasonable-sounding, and wrong in a way that only shows up once you rely on it.

63. Restore the missing line: Step 8 · Wire it up in main

Fill the middle

Fill in the blanks

From Step 8 · Wire it up in main — one line has had its right-hand side removed. Put it back.

public static void main(String[] args) rand.nextInt(100) + 1;}
}
printArray(array); // the recursive display
System.out.println(); // finish the row cleanly
}

Why: array[i] is what everything below it consumes, so the wrong expression here fails later and somewhere else. printArray can only display what the loop already stored - calling it before the loop would print 100 zeros.

64. Step 8 · Wire it up in main

Worked example

public static void main(String[] args) {
    int[] array = new int[100];
    Random rand = new Random();
    for (int i = 0; i < array.length; i++) {
        array[i] = rand.nextInt(100) + 1;
    }
    printArray(array);        // the recursive display
    System.out.println();     // finish the row cleanly
}

Fill first, print second

Why: printArray can only display what the loop already stored - calling it before the loop would print 100 zeros.

Call the one-argument printArray(array)

Why: Exactly the call the pseudo-code shows - the overload starts the recursion at index 0 for us.

orderactionassignment requirement met
1new int[100]100 elements in size
2for loop + nextInt(100) + 1filled by loop + RNG, 1..100 inclusive
3printArray(array)recursive display, space-separated

65. The complete program

Concept

import java.util.Random;

public class PrintArrayRecursion {

    // Matches the pseudo-code signature: printArray(integer array)
    public static void printArray(int[] array) {
        printArray(array, 0);
    }

    public static void printArray(int[] array, int index) {
        if (index == array.length) {   // base case: past the last element
            return;
        }
        System.out.print(array[index] + " ");
        printArray(array, index + 1);  // recursive step: rest of the array
    }

    public static void main(String[] args) {
        int[] array = new int[100];
        Random rand = new Random();
        for (int i = 0; i < array.length; i++) {
            array[i] = rand.nextInt(100) + 1;   // 1..100 inclusive
        }
        printArray(array);
        System.out.println();
    }
}
assignment requirementwhere it lives
recursive method printArray()the 2-arg method - calls itself on line with index + 1
displays all elements, space-separatedSystem.out.print(array[index] + " ")
array of 100 elementsnew int[100] in main
filled by for loop + RNG, 1..100the for loop with rand.nextInt(100) + 1
pseudo-code call printArray(array)the 1-arg overload

Twenty-seven lines, every sentence of the assignment accounted for. This exact file compiled and ran under OpenJDK 21 - the next slide shows its real output.

66. Predict the next row: Compile and run

Pattern

Predict first

The table runs: starts with | 65 41 38 58 13 96 29 9 66 61 ... · how many numbers | exactly 100 · all within 1..100? | yes - smallest seen 2, largest seen 100

In Compile and run, given the rows so far: what is the next one — the row where check on the real output is separated by?

Correct: separated by | single spaces, one row

check on the real outputresult from the verified run
starts with65 41 38 58 13 96 29 9 66 61 ...
how many numbersexactly 100
all within 1..100?yes - smallest seen 2, largest seen 100
separated bysingle spaces, one row

Why: The relationship between the columns, not the individual numbers, is what generates the next row. IDE users: the Run button does both.

67. Compile and run

Worked example

javac PrintArrayRecursion.java
java PrintArrayRecursion

javac compiles, java runs

Why: IDE users: the Run button does both. Command-line users: two commands, in this order, from the folder containing the file.

check on the real outputresult from the verified run
starts with65 41 38 58 13 96 29 9 66 61 ...
how many numbersexactly 100
all within 1..100?yes - smallest seen 2, largest seen 100
separated bysingle spaces, one row

Count before you celebrate

Why: The early-stop trap taught us wrong recursion can LOOK fine. Verify the count: in a terminal, or paste the row into an editor and check. 100 numbers, no zeros, nothing above 100.

68. Draw the shape of it: Compile and run

Blank canvas

Draw it

Draw what Compile and run just did — the shape of it, not the line-by-line working. One picture, labels only where you need them. Then check it against the steps: anything you could not draw is a step you followed rather than understood.

69. Read the output like a grader

Concept

Before any screenshot, audit the row the way the person grading it will. Each check corresponds to a requirement - and to one of the traps we defused:

audit questionwhat a failure would mean
exactly 100 numbers?an early-stop base case silently dropped some
any 0 anywhere?nextInt(100) without the + 1
anything above 100?wrong bound in nextInt
one row, single spaces?println crept back in
different numbers on a re-run?Random not actually used

Thirty seconds of auditing now beats resubmitting later. Correct-looking output that nobody counted is how the early-stop trap survives into submissions.

70. Check: what makes it recursive

Check

Check your understanding

Which single line makes printArray a recursive method?

  • A. if (index == array.length) { return; }
  • B. System.out.print(array[index] + " ");
  • C. printArray(array, index + 1); (correct)
  • D. int[] array = new int[100];

Answer: C

Why: A method is recursive precisely when it calls itself, and that is the line where printArray invokes printArray. The base case and the print line are essential supporting cast, but the self-call is what earns the word 'recursive' - and it is what the grader will look for in your code screenshot.

Why A tempts people
That is the base case - it is what STOPS the recursion. Necessary for correctness, but a method with only this line never calls itself.
Why B tempts people
That is the one piece of work each call performs. Printing is the method's job, not its recursive structure.
Why D tempts people
That line lives in main and just builds the array. It runs once and involves no method calling itself.

71. Part 4 · When It Breaks

Section

72. Reading the two crash messages

Concept

Both recursion crashes announce themselves clearly if you read the first line. These are the verbatim messages from our real broken runs:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException:
        Index 3 out of bounds for length 3
    at NoBaseCase.printArray(NoBaseCase.java:4)

Exception in thread "main" java.lang.StackOverflowError
    at NoProgress.printArray(NoProgress.java:8)
    at NoProgress.printArray(NoProgress.java:8)
    ... (the same line, 1000+ times)
crashtranslationfix
ArrayIndexOutOfBoundsExceptionrecursion ran PAST the end - base case missing or checking the wrong thingguard with index == array.length before touching array[index]
StackOverflowErrorrecursion never moved - calls piled up until the stack was fullmake sure the recursive call passes index + 1
same line repeated 1000+ times in the traceeach repeat is one stacked call of your methodthat repeated line number IS the bug's address

The wall of repeated at ... lines is not noise - it is the call stack from Part 2, printed out. You already know how to read it.

73. The two-question debug checklist

Concept

Any recursive method, any language, any bug - start with the same two questions from Part 1:

symptomquestion that finds itusual culprit
ArrayIndexOutOfBoundsExceptionIs there a base case, checked FIRST?no base case, or it is below the array access
StackOverflowError + repeating outputDoes every call move toward the base case?recursive call passes index, not index + 1
last element missingDoes the base case stop at exactly array.length?length - 1: stops one early, silently
prints 100 zerosDid the fill loop run before printArray?printArray called above the for loop

Note the fourth row crashes nothing and looks structurally fine - output you did not actually read is the failure mode screenshots are designed to catch.

74. Answer it before you see the options: Check: diagnose from the symptom

Prediction

Predict first

A student's program prints '43 43 43 43 43 ...' and then crashes with java.lang.StackOverflowError. Which bug is the most likely cause?

Answer it in your own words, now, with nothing to choose from. The options are on the next slide — and picking the right one off a list is an easier skill than producing it.

Correct: The recursive call passes index instead of index + 1.

Why: The same value repeating means the index never advances - every call re-prints its own element and hands off an identical problem, so calls pile up until the stack overflows. Our verified broken run showed exactly this shape: repeated output, then over a thousand identical stack frames.

75. Check: diagnose from the symptom

Check

Check your understanding

A student's program prints '43 43 43 43 43 ...' and then crashes with java.lang.StackOverflowError. Which bug is the most likely cause?

  • A. The import java.util.Random; line is missing.
  • B. The base case tests index == array.length - 1 instead of array.length.
  • C. The recursive call passes index instead of index + 1. (correct)
  • D. The array is too large for Java to handle.

Answer: C

Why: The same value repeating means the index never advances - every call re-prints its own element and hands off an identical problem, so calls pile up until the stack overflows. Our verified broken run showed exactly this shape: repeated output, then over a thousand identical stack frames.

Why A tempts people
A missing import is a COMPILE error - the program would never have run at all, let alone printed anything.
Why B tempts people
The off-by-one base case still advances the index every call, so it terminates fine - its symptom is one silently missing element, not a crash.
Why D tempts people
A 100-element int array is about 400 bytes - trivial. The stack overflowed from unbounded CALLS, not from the array's size.

76. Part 5 · Screenshots & Submission

Section

77. You only get credit for what you demonstrate

Concept

That sentence is in the assignment, verbatim. The grader will not run your code - the screenshots ARE the submission. So we capture them deliberately, against a checklist, before the session ends.

evidence requiredwhich screenshot provides it
the method is actually recursivecode screenshot: the self-call visible, no loop in printArray
array is 100 elements, filled by loop + RNGcode screenshot: new int[100] and the for loop visible
program runs and displays all elementsrun screenshot: the full row of 100 numbers
values are 1..100, space-separatedrun screenshot: readable numbers, no zeros
the numbers are genuinely randomsecond run screenshot: different numbers

Three screenshots total: the code, one run, a second run. Five minutes of careful capture protects the whole hour of work.

78. Screenshot 1 · The code

Concept

Frame the shot so the grader can verify recursion at a glance - the whole printArray method in view, nothing cropped.

must be visiblewhy the grader cares
both printArray methods, completethe self-call with index + 1 is the proof of recursion
no for/while inside printArraya loop in there means the recursion requirement was dodged
main: new int[100] + the fill loopthe 100-size and loop+RNG requirements
the file name / class nameties the code to the run screenshots

If your editor font is small, zoom in before capturing - an unreadable screenshot demonstrates nothing, and the assignment is explicit about what that earns.

79. Teach it back: Screenshot 1 · The code

Explain it

Discussion prompt

Explain Screenshot 1 · The code to a student a year behind you. No notation, no jargon they have not met — and it still has to be true.

Hint: If your explanation needs a symbol they have never seen, you are describing the notation rather than the idea.

Answer:

Frame the shot so the grader can verify recursion at a glance - the whole printArray method in view, nothing cropped.

80. Screenshots 2 and 3 · The runs

Concept

Now the program running - the part the assignment stresses. All 100 numbers must be visible and countable.

capture stepdetail
1. widen the console window first100 numbers wrap across only 2-3 lines when the window is wide
2. run, and capture command + output togetherthe java PrintArrayRecursion line above the output proves what produced it
3. scan before you snapno 0, nothing over 100, single spaces - the traps we defused
4. run AGAIN and capture the second outputdifferent numbers = the random generator is real, not hard-coded

The two-run pair is the cheapest insurance in the submission: it preempts the one question a skeptical grader always has - did the RNG actually run?

81. By analogy: Screenshots 2 and 3 · The runs

Analogy

Discussion prompt

Explain Screenshots 2 and 3 · The runs by analogy to something with no Java in it at all — a queue, a recipe, a map, a bank balance, whatever fits. Then say where your analogy breaks.

Hint: An analogy that never breaks is not an analogy, it is the same idea wearing a hat. Find the seam — that is the part that is actually new.

Answer:

The two-run pair is the cheapest insurance in the submission: it preempts the one question a skeptical grader always has - did the RNG actually run?

82. If the console cuts the row off

Concept

A narrow console wraps or scrolls 100 numbers, and a screenshot missing part of the output demonstrates only part of the assignment. Fallbacks, in order of preference:

optionhow
widen the window firstmaximize the terminal/IDE console before running - usually fits in 2-3 lines
zoom out one stepCtrl+Minus in most terminals and IDE consoles shrinks the font enough
take two overlapping screenshotsshot 1: command + first half; shot 2: second half + the prompt returning
scroll-capturesome tools capture the whole scrollback as one tall image

Whatever you choose, the pair (command that ran) + (complete output) must be reconstructible by the grader from your images alone.

83. Break it if you can: If the console cuts the row off

Counterexample

Discussion prompt

A narrow console wraps or scrolls 100 numbers, and a screenshot missing part of the output demonstrates only part of the assignment. Fallbacks, in order of preference:

That is stated as though it always holds. Do one of two things: produce a case where it fails, or say precisely what rules such a case out. "It just does" is not on the menu.

Hint: Hunt at the extremes first — zero, one, negative, empty, equal. If every extreme survives, the reason they survive is the proof.

Answer:

Whatever you choose, the pair (command that ran) + (complete output) must be reconstructible by the grader from your images alone.

84. Part 6 · Prove You Own It

Section

85. What has to be given first: Print it backwards - by swapping two lines

Missing information

Discussion prompt

The assignment is done. Now the ownership test: make it print the array backwards - changing nothing but the order of two lines.

What do you need to know — or decide — before the first line can be written? List everything the problem has to hand you.

Hint: Anything you would have to invent to get started is a thing the problem must supply.

Answer:

Each call now stays quiet on the way down. The printing happens during the UNWIND - the return trip Part 2 said would become interesting.

86. Print it backwards - by swapping two lines

Worked example

The assignment is done. Now the ownership test: make it print the array backwards - changing nothing but the order of two lines.

public static void printBackwards(int[] array, int index) {
    if (index == array.length) {
        return;
    }
    printBackwards(array, index + 1);       // recurse FIRST
    System.out.print(array[index] + " ");   // print on the way BACK
}

Recurse before printing

Why: Each call now stays quiet on the way down. The printing happens during the UNWIND - the return trip Part 2 said would become interesting.

phasecallprints
downindex 0 -> 1 -> 2 -> 3 (base case)nothing yet
back upcall at index 2 resumes9
back upcall at index 1 resumes2
back upcall at index 0 resumes7

Verify against the real run

Why: Compiled and executed on {7, 2, 9}: output is exactly 9 2 7. With a loop this reversal means rewriting the header; with recursion it was a two-line swap.

87. Work backwards from the answer: Print it backwards - by swapping two lines

Reverse engineer

Discussion prompt

Work backwards. The example finished here:

Verify against the real run

What was it asked to do, and what must it have been given? Reconstruct the problem from its answer.

Hint: Every quantity in the result had to enter somewhere. Account for each one.

Answer:

The assignment is done. Now the ownership test: make it print the array backwards - changing nothing but the order of two lines.

88. Rule out three: Check: the swap

Elimination

Eliminate the wrong options

Inside a correct printArray, the print line and the recursive call are swapped, so the method recurses first and prints after. Running it on {7, 2, 9} - what happens?

3 of these 4 are wrong. Strike them one at a time, and say what rules each one out before you strike the next. The survivor is the answer.

  • A. It prints 7 2 9, same as before.
  • B. It prints 9 2 7 - the array backwards.
  • C. It crashes with StackOverflowError.
  • D. It prints nothing at all.

Survives elimination: B

Why: With the recursive call first, every call dives all the way to the base case before any printing happens; each call then prints its element as the stack unwinds, deepest call first. The verified run outputs exactly 9 2 7. Where a line sits relative to the recursive call decides whether it runs on the way down or the way back.

89. Check: the swap

Check

Check your understanding

Inside a correct printArray, the print line and the recursive call are swapped, so the method recurses first and prints after. Running it on {7, 2, 9} - what happens?

  • A. It prints 7 2 9, same as before.
  • B. It prints 9 2 7 - the array backwards. (correct)
  • C. It crashes with StackOverflowError.
  • D. It prints nothing at all.

Answer: B

Why: With the recursive call first, every call dives all the way to the base case before any printing happens; each call then prints its element as the stack unwinds, deepest call first. The verified run outputs exactly 9 2 7. Where a line sits relative to the recursive call decides whether it runs on the way down or the way back.

Why A tempts people
Order relative to the recursive call is everything: printing BEFORE the call gives forward order on the way down; printing AFTER gives reverse order on the unwind.
Why C tempts people
The base case and the index + 1 are untouched, so the recursion still terminates after exactly 4 calls - only the timing of the print moved.
Why D tempts people
The print line still executes once per element - just after each call's recursive work finishes instead of before. Every element is printed exactly once.

90. Guess the shape of the answer: Transfer: a recursive sum

Estimation

Predict first

Same skeleton, different work: instead of printing each element, add it. This is the from-scratch exercise to try solo after the session:

Commit before you compute: what does Transfer: a recursive sum come out to? A rough magnitude and the right form is enough — the point is to have something concrete to be wrong about.

Correct: Verify: real run on {7, 2, 9} returned 18

Why: A prediction you can defend turns the computation into a check rather than a leap of faith — and an answer that contradicts it is caught on the spot. Read the table bottom-up to watch the answers assemble during the unwind - the same return trip that printed backwards a moment ago.

91. Transfer: a recursive sum

Worked example

Same skeleton, different work: instead of printing each element, add it. This is the from-scratch exercise to try solo after the session:

public static int sum(int[] array, int index) {
    if (index == array.length) {
        return 0;                              // empty rest adds nothing
    }
    return array[index] + sum(array, index + 1);
}

The base case now returns a VALUE

Why: A void method just stops; a summing method must answer. The sum of nothing is 0 - the identity that makes the additions work.

callcomputesreturns
sum(arr, 0)7 + sum(arr, 1)7 + 11 = 18
sum(arr, 1)2 + sum(arr, 2)2 + 9 = 11
sum(arr, 2)9 + sum(arr, 3)9 + 0 = 9
sum(arr, 3)base case0

Verify: real run on {7, 2, 9} returned 18

Why: Read the table bottom-up to watch the answers assemble during the unwind - the same return trip that printed backwards a moment ago.

92. Inspect it line by line: Transfer: a recursive sum

Error analysis

Annotate

Walk the callouts on Transfer: a recursive sum. Each one is a place this is easy to get subtly wrong.

  • A void method just stops; a summing method must answer. The sum of nothing is 0 - the identity that makes the additions work.
  • Read the table bottom-up to watch the answers assemble during the unwind - the same return trip that printed backwards a moment ago.

93. Loop vs recursion: an honest comparison

Concept

questionlooprecursion
print an array forwardsnaturalworks - as you proved today
print it backwardsrewrite the loop headerswap two lines
memory usedone frameone frame per element (101 here)
walk folders inside foldersgenuinely painfulnatural - it IS the shape of the data
risk profileoff-by-one boundsmissing base case / not shrinking

For THIS assignment a loop would be simpler - the assignment chose recursion because the mechanism is the lesson. The payoff arrives with nested structures: folders, trees, and the divide-and-conquer algorithms in your upper-level courses, where recursion is not the alternative but the only sane option.

94. What each one costs: Loop vs recursion: an honest comparison

Trade off

Comparison matrix

From Loop vs recursion: an honest comparison: every row here is a choice with a cost. Fill the recursion column, then say which row you would actually pick and what you give up for it.

questionlooprecursion
print an array forwardsnaturalworks - as you proved today
print it backwardsrewrite the loop headerswap two lines
memory usedone frameone frame per element (101 here)
walk folders inside foldersgenuinely painfulnatural - it IS the shape of the data
risk profileoff-by-one boundsmissing base case / not shrinking

95. Where you will meet recursion next

Intuition

Folders: a folder holds files and more folders. Printing every file name is printArray with folders as the 'rest' - and the base case is a folder with nothing left inside.

Binary search: check the middle of a sorted array, then search the half that could contain the target. The problem halves every call - base case: one element left.

Sorting: merge sort splits the array in two, recursively sorts each half, and merges. Every one of these is today's skeleton - base case, one piece of work, recurse on something smaller.

96. Questions students always ask

Concept

Why not just use a loop?
For this task a loop is fine - the assignment is teaching the mechanism. Backwards printing already showed the payoff, and folder trees will make it undeniable.
Does recursion use more memory?
Yes - one stack frame per active call, so 101 frames for the 100-element array. Java handles thousands of frames comfortably; it only becomes a design concern at much larger depths.
Is the for loop in main cheating?
No - the assignment explicitly says to FILL the array with a for loop. Only printArray has to be recursive, and yours is.
Are two methods named printArray legal?
Yes - that is overloading: same name, different parameter lists. Java picks by the arguments at the call site. It is how we honored the pseudo-code's one-argument call.

97. Which is which: Questions students always ask

Matching

Match the pairs

From Questions students always ask — match each one to what it actually does. The descriptions have been shuffled.

  • c1. Why not just use a loop?
  • c2. Is the for loop in main cheating?
  • c3. Are two methods named printArray legal?
  • b1. For this task a loop is fine - the assignment is teaching the mechanism. Backwards printing already showed the payoff, and folder trees will make it undeniable.
  • b2. No - the assignment explicitly says to FILL the array with a for loop. Only printArray has to be recursive, and yours is.
  • b3. Yes - that is overloading: same name, different parameter lists. Java picks by the arguments at the call site. It is how we honored the pseudo-code's one-argument call.

Why: Why not just use a loop?, Is the for loop in main cheating?, Are two methods named printArray legal? are easy to tell apart while they are sitting next to their descriptions and much harder afterwards, which is what this checks.

98. Final pre-submission checklist

Concept

#verify before submittingdone
1printArray calls itself with index + 1; no loop inside it[ ]
2base case is index == array.length, checked first[ ]
3new int[100], filled by for loop with nextInt(100) + 1[ ]
4output: 100 numbers, spaces, no zeros, nothing over 100[ ]
5screenshot: code with the recursive method fully visible[ ]
6screenshots: TWO runs with different numbers[ ]

Every row maps to a sentence in the assignment. Six check marks = the whole rubric is demonstrated, which is the only currency this assignment pays out in.

99. Fill in: done for Final pre-submission checklist

Comparison

Comparison matrix

From Final pre-submission checklist: refill the done column from what you know. The rest of the table is as it appeared.

#verify before submittingdone
1printArray calls itself with index + 1; no loop inside it[ ]
2base case is index == array.length, checked first[ ]
3new int[100], filled by for loop with nextInt(100) + 1[ ]
4output: 100 numbers, spaces, no zeros, nothing over 100[ ]
5screenshot: code with the recursive method fully visible[ ]
6screenshots: TWO runs with different numbers[ ]

100. Vocabulary recap

Concept

Recursive method — A method that calls itself, directly or indirectly, handling one piece of the problem per call.

Base case — The stopping condition, checked first: for printArray, index == array.length.

Recursive step — The self-call on a strictly smaller problem: printArray(array, index + 1).

Call stack — Java's tower of paused calls - it grows one frame per call on the way down and unwinds as returns cascade back.

Overloading — Two methods sharing a name with different parameter lists - how printArray(array) and printArray(array, index) coexist.

StackOverflowError — The crash when calls pile up without progress toward a base case - diagnosed by the same line repeating 1000+ times in the trace.

101. Term to definition: Recursion - Building the printArray() Assignment

Matching

Match the pairs

Match each term to the definition this lesson gave it — not the one you would guess from the word.

  • t1. Base case
  • t2. Recursive step
  • t3. Recursive method
  • t4. Call stack
  • t5. Overloading
  • d1. The condition under which the method does NOT call itself - it just stops (returns). For printArray: the index has walked past the last element.
  • d2. The line where the method calls itself on a smaller version of the problem. For printArray: print one element, then call yourself with index + 1.
  • d3. A method that calls itself, directly or indirectly, handling one piece of the problem per call.
  • d4. Java's tower of paused calls - it grows one frame per call on the way down and unwinds as returns cascade back.
  • d5. Two methods sharing a name with different parameter lists - how printArray(array) and printArray(array, index) coexist.

Why: These are the working definitions of Base case, Recursive step, Recursive method, Call stack, Overloading as Recursion - Building the printArray() Assignment uses them. Pairing them correctly is the test of whether you could state each one with the slide switched off.

102. Connect it up: Recursion - Building the printArray() Assignment

Connect it up

Draw it

One page, no notation unless you need it: draw how these connect — Part 1 · What Is Recursion? · Part 2 · Trace It by Hand · Part 3 · Build the Assignment · Part 4 · When It Breaks · Part 5 · Screenshots & Submission · Part 6 · Prove You Own It. Put an arrow wherever one of them is what makes another possible, and label the arrow with why.

103. What you built and what you know

Recap

The assignment is done. A recursive printArray - base case first, one print, then the self-call with index + 1 - displaying a 100-element array filled by a for loop with rand.nextInt(100) + 1. Compiled, run, verified, screenshotted twice.

The mechanism is yours. You traced 4 calls for 3 elements, drew the stack growing and unwinding, and used the unwind on purpose: swapping two lines printed the array backwards - 9 2 7 - with no other change.

The crashes are familiar. No base case: ArrayIndexOutOfBoundsException. No progress toward it: repeated output, then StackOverflowError with the same line stacked 1000+ deep. Two questions diagnose every recursive bug: is there a base case, and does every call move toward it?

Next: the homework's recursive sum and countEven use today's skeleton with different work per call. When they feel easy, you are ready for the recursion that halves problems instead of shrinking them by one - binary search.

Sources

  1. The Java Tutorials - Defining Methods (Oracle)
  2. Java SE 21 API - java.util.Random
  3. Java SE 21 API - java.lang.StackOverflowError
  4. All snippets compiled and executed under OpenJDK Temurin 21.0.11; outputs, error messages and stack traces copied verbatim from real runs. — Author verification run, 2026-08-08.

Want this taught 1-on-1? Alexander tutors Java — $55/session, free consultation.

Book on Wyzant · Text (657) 465-8108