AP COMPUTER SCIENCE A • DATA COLLECTIONS

Implementing Array Algorithms

Master the classic traversal, search, and accumulation patterns that form the backbone of array processing in Java.

Historical Context & Motivation

Arrays are among the oldest and most fundamental data structures in computing, dating back to the earliest programming languages of the 1950s. The need to store and process ordered collections of homogeneous data—sensor readings, student grades, pixel values—drove language designers to provide contiguous memory blocks accessible by index. With arrays came the necessity for array algorithms: repeatable, well-defined procedures for traversing, searching, sorting, and transforming array contents. These algorithms have been refined over decades and remain central to virtually every software system written today.

1957
FORTRAN & Array Processing
IBM's FORTRAN—the first widely used high-level language—introduced fixed-size arrays and DO loops, establishing the traversal pattern still used in Java today.
1962
Binary Search Formalized
While the idea existed earlier, formal analysis of binary search's O(log n) performance appeared in the 1960s, contrasting it with the O(n) linear scan and motivating the study of algorithmic efficiency.
1995
Java's Array Model
Java shipped with zero-indexed, bounds-checked arrays and a for loop, combining C-style indexing with runtime safety via ArrayIndexOutOfBoundsException.
2004
Enhanced for Loop (Java 5)
The for-each loop simplified read-only traversals, reducing off-by-one errors and making intent clearer—a pattern heavily tested on the AP exam.

Despite the proliferation of higher-level collections such as ArrayList, raw array algorithms remain essential because they expose the logic beneath library methods. The AP Computer Science A exam tests your ability to write, trace, and reason about these algorithms without relying on built-in helpers. The central question this lesson addresses is: How do you design, implement, and verify standard array algorithms in Java?

Core Principles & Definitions

Every array algorithm in the AP CSA curriculum builds on a small set of foundational ideas. Understanding these principles lets you decompose unfamiliar problems into combinations of patterns you already know, rather than memorizing dozens of isolated code snippets.

1

Traversal

Visiting every element exactly once using a standard for or enhanced for-each loop. This is the backbone of all other array algorithms.
2

Accumulation

Building a running result—sum, product, count, or concatenated string—by combining each element with an accumulator variable initialized before the loop.
3

Search

Linear search scans left-to-right for a target, returning the index or −1. It works on unsorted data and runs in O(n) time in the worst case.
4

Extreme Value Detection

Finding the minimum or maximum by initializing a candidate to the first element, then comparing against every subsequent element and updating when a more extreme value is found.
5

Shift & Insert

Rearranging elements in place—shifting right to open a gap, shifting left to close one, or reversing—requires careful index management to avoid overwriting data.
KEY TAKEAWAY
KEY TAKEAWAY

Visual Explanation — Traversal Patterns

The top row shows index-based traversal where i provides direct positional access. The bottom row shows the enhanced for-each loop, which yields a copy of each element's value. Use the index-based form when you need to modify elements or know their position; use for-each for read-only operations.

The diagram above illustrates the two traversal idioms you will encounter on the AP exam. The index-based for loop gives you full control: you can read and write elements, traverse in reverse, skip indices, or compare adjacent pairs. The enhanced for-each loop is more concise but provides only a read-only copy of each element. Assigning a new value to the loop variable does not alter the underlying array—a common source of errors and a favorite exam distractor.

How Array Algorithms Work

The Accumulation Pattern

Accumulation algorithms follow a predictable template: declare an accumulator variable before the loop, update it inside the loop, and use it after the loop. The type and initial value of the accumulator depend on the operation. For a sum you initialize to 0; for a product, to 1; for a maximum, to arr[0] (or Integer.MIN_VALUE). Getting the initial value wrong is the most common bug in accumulation code.

SUM ACCUMULATION
sum = Σ arr[i] for i = 0 … n−1
In Java: int sum = 0; for (int v : arr) sum += v; | n = arr.length
AVERAGE
avg = sum / n (integer division truncates)
Cast to double before dividing if a decimal result is needed: (double) sum / arr.length

Linear Search

A linear search examines elements from index 0 onward, returning the index of the first match or −1 if no match is found. The algorithm's worst-case running time is proportional to the number of elements, which we express as O(n). A key implementation detail: use return inside the loop for an early exit as soon as the target is found—do not continue scanning needlessly.

Min / Max Detection

Finding the minimum or maximum follows the accumulation pattern with a comparison-based update. Initialize a variable max to arr[0], then loop from index 1 onward. Each iteration compares arr[i] to max and updates if the current element is larger. Starting the loop at index 1 is valid because the accumulator already holds arr[0]; starting at index 0 merely performs one redundant comparison—not an error, but slightly less efficient.

AP Exam Tip

Detailed Algorithm Catalog

This diagram shows the shift-right-to-insert algorithm. Elements at indices 2–4 are copied one position to the right (working from back to front to avoid overwriting), creating space at index 2 for the new value 99. The orange cells show data in transit; the green cell shows the final insertion.
Common array algorithms tested on the AP CSA exam
AlgorithmLoop DirectionKey Detail
Sum / AverageForward (0 → n−1)Initialize accumulator to 0; cast to double before dividing for decimal average
Linear SearchForward, early exitReturn index on match; return −1 after loop if not found
Min / MaxForward (1 → n−1)Initialize to arr[0], not 0 or Integer.MAX_VALUE
Count MatchesForward (for-each OK)Increment counter when condition is true
Shift Right (Insert)Backward (n−1 → idx)Must go back-to-front to avoid overwriting; array must have capacity
Shift Left (Remove)Forward (idx → n−2)Overwrite target, then shift remaining left; set last active cell to default
ReverseTwo pointers (0 ↔ n−1)Swap arr[lo] and arr[hi], then lo++, hi−−; stop when lo ≥ hi

Worked Example — Finding the Second Largest

A frequently tested variation asks you to find the second largest value in an array without sorting. This problem combines the min/max pattern with an additional tracking variable.

1
Step 1 — Understand the ProblemGiven int[] arr = {7, 3, 9, 1, 9, 5}, return the second largest distinct value. Here the answer should be 7 because 9 is the largest.
2
Step 2 — Initialize Two TrackersDeclare int max = Integer.MIN_VALUE and int second = Integer.MIN_VALUE. Using Integer.MIN_VALUE avoids assumptions about the data range.
3
Step 3 — Single-Pass TraversalFor each element, check two conditions in order. If arr[i] > max, demote the current max to second, then update max. Otherwise, if arr[i] > second && arr[i] != max, update second only. The != max guard ensures duplicates of the max are not counted as the second largest.
4
Step 4 — Trace the Iterationi=0: arr[0]=7 > MIN → second=MIN, max=7. i=1: 3 < 7 and 3 > MIN → second=3. i=2: 9 > 7 → second=7, max=9. i=3: 1 < 9 and 1 < 7 → skip. i=4: 9 == max → skip. i=5: 5 < 9 and 5 < 7 → skip.
max = 9, second = 7
5
Step 5 — Write the Codepublic static int secondLargest(int[] arr) { int max = Integer.MIN_VALUE; int second = Integer.MIN_VALUE; for (int v : arr) { if (v > max) { second = max; max = v; } else if (v > second && v != max) { second = v; } } return second; }

Strengths, Limitations & Loop Selection

When to use each loop form
FeatureIndex-Based for LoopEnhanced for-each Loop
Read elements
Modify elements✓ (via arr[i] = …)✗ (loop var is a copy)
Access index
Traverse backwards
Compare neighbors✓ (arr[i] vs arr[i+1])✗ (only one element visible)
Conciseness / readabilityModerateHigh
Risk of off-by-one errorHigher (manual bounds)Low (managed by JVM)
KEY TAKEAWAY
KEY TAKEAWAY

Connection to ArrayList & Advanced Topics

The algorithms you learn for primitive arrays transfer directly to ArrayList and other collections. The key difference is that ArrayList handles resizing, insertion, and deletion internally, so you replace index-based access with method calls like get(i), set(i, val), and remove(i). Understanding the underlying shift-left and shift-right mechanics helps you predict the O(n) cost of ArrayList insertions and removals—something the exam frequently tests through tracing questions.

Array vs ArrayList syntax comparison
OperationArray (manual)ArrayList (built-in)
Access by indexarr[i]list.get(i)
Update by indexarr[i] = vallist.set(i, val)
Insert at indexManual shift-right looplist.add(i, val)
Remove at indexManual shift-left looplist.remove(i)
Sizearr.lengthlist.size()
Resizable?No — fixed at creationYes — grows automatically

Looking ahead, the selection sort and insertion sort algorithms you will study in Unit 7 are built entirely from the traversal, comparison, and swap primitives covered in this lesson. Mastering array algorithms now ensures that sorting algorithms feel like natural extensions rather than new topics.

Practice Problems

1
Consider the following code segment. int[] nums = {4, 7, 2, 9}; for (int val : nums) { val = val * 2; } System.out.println(nums[1]); What is printed?
2
What value is returned by the following method when called with {3, -1, 4, -1, 5}? public static int mystery(int[] a) { int result = 0; for (int i = 0; i < a.length; i++) { if (a[i] > 0) result += a[i]; } return result; }
3
Consider the following method. public static int[] remove(int[] arr, int idx) { int[] result = new int[arr.length - 1]; for (int i = 0; i < idx; i++) result[i] = arr[i]; for (int i = idx; i < result.length; i++) result[i] = arr[i + 1]; return result; } If arr = {10, 20, 30, 40, 50} and idx = 2, what does the returned array contain?
PROBLEM 4APPLIED
Write a method public static double[] normalize(double[] data) that returns a new array where each element is scaled so the minimum value becomes 0.0 and the maximum becomes 1.0. Use the formula: normalized[i] = (data[i] − min) / (max − min). You may assume the array has at least two distinct values.
PROBLEM 5CRITICAL THINKING
Write a method public static boolean isSorted(int[] arr) that returns true if the array is sorted in non-decreasing order and false otherwise. An empty array or single-element array is considered sorted. Explain the time complexity and why a for-each loop would be inappropriate here.
Varsity Tutors • AP Computer Science A • Implementing Array Algorithms