Lesson 4.17: Recursive Searching and Sorting

AP CSA Hub Unit 4 4.1 Lesson Ex 1 Ex 2 Quiz 4.2 Lesson Ex 1 Ex 2 Quiz 4.3 Lesson Ex 1 Ex 2 Quiz 4.4 Lesson Ex 1 Ex 2 Quiz 4.5 Lesson Ex 1 Ex 2 Quiz 4.6 Lesson Ex 1 Ex 2 Quiz 4.7 Lesson Ex 1 Ex 2 Quiz 4.8 Lesson Ex 1 Ex 2 Quiz 4.9 Lesson Ex 1 Ex 2 Quiz 4.10 Lesson Ex 1 Ex 2 Quiz 4.11 Lesson Ex 1 Ex 2 Quiz 4.12 Lesson Ex 1 Ex 2 Quiz 4.13 Lesson Ex 1 Ex 2 Quiz 4.14 Lesson Ex 1 Ex 2 Quiz 4.15 Lesson Ex 1 Ex 2 Quiz 4.16 Lesson Ex 1 Ex 2 Quiz 4.17 Lesson Ex 1 Ex 2 Quiz

Unit 4 · Lesson 4.17 · Recursive Searching and Sorting

Lesson 4.17: Recursive Searching and Sorting

🕒 45-55 min · 10 Practice Questions · Recursive Search · Merge Sort · Divide and Conquer

What You'll Learn

  • Implement a recursive binary search using low/high parameters that narrow the range with each call.
  • Implement recursive merge sort, which splits an array, recursively sorts each half, and merges the results.
  • Explain why merge sort's split-and-recurse structure needs recursion while its merge step does not.
  • Count recursive calls, including the call that reaches the base case.

Key Vocabulary

Term Definition
recursive binary search The same halving search restated as a method that calls a smaller version of itself instead of looping.
merge sort A recursive sort that splits an array in half, recursively sorts each half, then merges the two sorted halves back together.
divide and conquer Breaking a problem into smaller versions of itself, solving each one, then combining the results.
base case The condition where a recursive method stops calling itself and returns directly.

Recursive Binary Search

Instead of a loop, the range narrows with each recursive call. The base case is an empty range: nothing left to check.

public static int binarySearch(int[] data, int target, int low, int high) {
    if (low > high) {
        return -1;
    }
    int mid = (low + high) / 2;
    if (data[mid] == target) {
        return mid;
    } else if (data[mid] < target) {
        return binarySearch(data, target, mid + 1, high);
    } else {
        return binarySearch(data, target, low, mid - 1);
    }
}

Recursive Merge Sort

Merge sort splits the array in half, recursively sorts each half, then merges the two already-sorted halves back into one sorted array.

public static int[] mergeSort(int[] data) {
    if (data.length <= 1) {
        return data;
    }
    int mid = data.length / 2;
    // split into left (0..mid-1) and right (mid..end)
    int[] sortedLeft = mergeSort(left);
    int[] sortedRight = mergeSort(right);
    return merge(sortedLeft, sortedRight);
}

📌 The Merge Step Does Not Need to Be Recursive

Recursion fits a problem that reduces to a smaller version of itself. Splitting the array down to single elements is exactly that. Combining two ALREADY-sorted halves back together is a single linear pass with no smaller version of itself to recurse into, which is why merge is conventionally written with a loop even though mergeSort around it is recursive.

⚠️ A Missing Base Case Never Stops

Without the length <= 1 check, mergeSort keeps trying to split arrays that are already down to 0 or 1 elements, forever, eventually causing a StackOverflowError.

Practice Questions

MCQ 1
A recursive binary search is called with low=0 and high=-1. What should happen?
A Compute mid and keep searching
B This is the base case: the range is empty (low > high), so return immediately, typically -1
C This causes infinite recursion
D This call should never occur under any circumstances
B. low > high signals an exhausted range, which is exactly the condition checked first, before mid is ever computed.
MCQ 2
What is the base case of a recursive mergeSort(int[] data) method?
A data.length == 0 only
B An array of length 0 or 1, which is already sorted by definition
C There is no base case; mergeSort runs until the array is empty
D data[0] == 0
B. A single element (or none) cannot be out of order relative to itself, so it needs no further splitting.
MCQ 3
Why does merge sort's merge STEP not need to be recursive, even though the surrounding sort is?
A Merging two already-sorted lists is one linear pass with no smaller version of the same problem to recurse into
B Recursion is only allowed once per method in Java
C Merging is actually recursive too, just hidden from view
D Merge could be written recursively, but Java forbids it
A. Recursion fits problems with a natural smaller-subproblem structure. Combining two sorted lists is not that kind of problem.
MCQ 4
An array of length 7 is split for merge sort using mid = data.length / 2. What are the lengths of the two halves?
A 3 and 4
B 4 and 3
C 3 and 3
D 4 and 4
A. 7 / 2 is 3 under integer division. The left half gets indices 0-2 (length 3), the right half gets the rest (length 4).
MCQ 5
What happens if a recursive mergeSort has no base case check at all?
A It sorts correctly but slowly
B It recurses forever trying to split arrays that are already length 0 or 1, eventually causing a StackOverflowError
C It sorts the array in reverse order
D Java automatically inserts a base case for you
B. Every recursive method needs an explicit stopping condition; without one, the calls never stop.
Tier 3 · AP Mastery

Mastery: Recursive Searching and Sorting

MCQ 6
How many recursive calls does binarySearch make (including the one that matches) to find target=13 in [1,3,5,7,9,11,13]?
A 1
B 2
C 3
D 7
C. Call 1: mid=3 (value 7, low goes up). Call 2: mid=5 (value 11, low goes up). Call 3: mid=6 (value 13, match). Three calls.
MCQ 7
How many total calls does binarySearch make for target=4 (not present) on [1,3,5,7,9,11,13]?
A 2
B 3
C 4
D 7
C. Call 1: mid=3 (value 7, high goes down). Call 2: mid=1 (value 3, low goes up). Call 3: mid=2 (value 5, high goes down). Call 4: low > high, base case returns -1. Four calls.
MCQ 8
mergeSort splits [8,3,5,1,9,2] (length 6) using mid = data.length / 2. What are the two halves?
A [8,3,5] and [1,9,2]
B [8,3] and [5,1,9,2]
C [8,3,5,1] and [9,2]
D [8] and [3,5,1,9,2]
A. mid = 6 / 2 = 3. The left half is indices 0-2, the right half is indices 3-5.
MCQ 9
What does mergeSort([5]) return, and why?
A [5], because an array of length 1 hits the base case and is returned unchanged, already sorted
B [], because length-1 arrays are treated as empty
C This throws an exception, since there is nothing to merge
D It infinitely recurses trying to split a single element
A. length <= 1 is true, so the base case returns the array exactly as given.
MCQ 10
A method searchCalls mirrors binarySearch but counts calls instead of finding an index. Why does its base case return 1, not 0?
A It is an arbitrary stylistic choice with no real reason
B The base case call is itself a real call in the chain and must contribute 1 to the total, or the count would always be one short of the actual number of calls made
C Returning 0 in the base case would not compile
D The final count must always be an even number
B. Every invocation of the method, including the one that hits the base case, is a call that happened and needs to be counted.

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]