CompSci.rocks
FRQcsapa

Trip: 2008 FRQ 1

A step-by-step solution to the 2008 AP CSA FRQ 1 (Trip), covering ArrayList traversal, accumulating a total duration, and tracking a running minimum across a list of flights in Java.

A travel agency's list of connecting flights drives this AP Computer Science A free-response question — you total up how long an entire trip takes from start to finish, then hunt through it for the tightest connection between any two flights.

What This FRQ Tests

  • AP CSA units: Unit 6 (Array) and Unit 7 (ArrayList)
  • Core skill: traversing an ArrayList of custom objects to accumulate and compare values pulled from a helper method
  • Secondary skill: recognizing when a special case (an empty list, or a list too short to have a layover) needs to be handled before the main loop logic even runs
  • Official category: officially FRQ 1 by this exam's own printed numbering — but 2008 predates the fixed FRQ-number-to-category order introduced with the 2019–2020 CED redesign. Content-wise, this is actually an Array/ArrayList question (traversing an ArrayList<Flight>), not a "Methods and Control Structures" one, despite sitting in the FRQ 1 slot.

The Setup

  • A Time class (not modified) provides one method:
    • int minutesUntil(Time other) — the number of minutes from this time to other; negative if other is earlier
  • A Flight class (not modified) provides:
    • Time getDepartureTime()
    • Time getArrivalTime()
  • A Trip class holds:
    • private ArrayList<Flight> flights — the flights of the trip, stored in chronological order
  • You're asked to write two methods:
    • getDuration() — minutes from the first flight's departure to the last flight's arrival
    • getShortestLayover() — the smallest gap between one flight's arrival and the next flight's departure

Part (a): Writing getDuration()

The Rule, Broken Down

  1. If there are no flights at all, the duration is 0.
  2. Otherwise, the duration is the time from the first flight's departure to the last flight's arrival — not the sum of each individual flight's own flying time, and not something that needs the layovers added in separately, since they're already included between those two endpoints.

Step-by-Step Approach

  1. Check whether flights is empty; if so, return 0 immediately.
  2. Otherwise, get the first flight (index 0) and the last flight (index flights.size() - 1).
  3. Call minutesUntil on the first flight's departure time, passing in the last flight's arrival time.
  4. Return that result.

The Code

public int getDuration()
{
    if (flights.size() == 0)
    {
        return 0;
    }

    Flight first = flights.get(0);
    Flight last = flights.get(flights.size() - 1);

    return first.getDepartureTime().minutesUntil(last.getArrivalTime());
}

Why Each Piece Matters

  • Checking flights.size() == 0 first — calling flights.get(0) on an empty list would throw an exception, so the empty case has to be handled before anything else runs.
  • flights.size() - 1 for the last flight — the trip can have any number of flights, so the last index always has to be computed, never hardcoded.
  • Calling minutesUntil on the first flight's departure, not the last flight's arrivalminutesUntil returns a value relative to this time, so first.getDepartureTime().minutesUntil(last.getArrivalTime()) reads as "minutes from the first departure to the last arrival," which is exactly the duration being asked for. Calling it the other way around would return the same distance as a negative number.

Part (b): Writing getShortestLayover()

The Rule, Broken Down

  1. A layover is the number of minutes between one flight's arrival and the very next flight's departure.
  2. If there are fewer than two flights, there's no layover to measure at all — return -1.
  3. Otherwise, return the smallest layover found across every consecutive pair of flights.

Step-by-Step Approach

  1. Check whether flights.size() is less than 2; if so, return -1 immediately.
  2. Compute the layover between the first two flights and use it as the starting "shortest" value.
  3. Loop through the remaining consecutive pairs of flights.
  4. For each pair, compute that layover and compare it to the current shortest, replacing it if this one is smaller.
  5. After the loop, return the shortest layover found.

The Code

public int getShortestLayover()
{
    if (flights.size() < 2)
    {
        return -1;
    }

    int shortest = flights.get(0).getArrivalTime().minutesUntil(flights.get(1).getDepartureTime());

    for (int i = 1; i < flights.size() - 1; i++)
    {
        int layover = flights.get(i).getArrivalTime().minutesUntil(flights.get(i + 1).getDepartureTime());

        if (layover < shortest)
        {
            shortest = layover;
        }
    }

    return shortest;
}

Why Each Piece Matters

  • flights.get(i).getArrivalTime().minutesUntil(flights.get(i + 1).getDepartureTime()) — this is "this flight's arrival" calling minutesUntil on "the next flight's departure," which is precisely how a layover is defined in the problem.
  • The loop only runs while i < flights.size() - 1i + 1 is used inside the loop body, so i can never be allowed to reach the last valid index, or flights.get(i + 1) would run off the end of the list.
  • Seeding shortest with the first pair's layover, instead of 0 or some arbitrary sentinel — since a real layover from this data is guaranteed to exist once there are at least two flights, starting from an actual computed value avoids having to guess what a "safe" starting number would be.

Tracing the Example

Using the question's own vacation example — four flights with these departure/arrival times:

Flight Departure Arrival Layover to next
0 11:30 a.m. 12:15 p.m. 60
1 1:15 p.m. 3:45 p.m. 15
2 4:00 p.m. 6:45 p.m. 210
3 10:15 p.m. 11:00 p.m.
  • shortest starts at the layover between Flight 0 and Flight 1: 60.
  • i = 1: layover between Flight 1 and Flight 2 is 15, which is less than 60, so shortest becomes 15.
  • i = 2: layover between Flight 2 and Flight 3 is 210, which is not less than 15, so shortest stays 15.
  • Final result: 15 — matches vacation.getShortestLayover() exactly, as stated in the question.

The question doesn't give a directly stated expected value for getDuration() on this same data (only for getShortestLayover()), but the same table lets us check it ourselves: from Flight 0's departure (11:30 a.m.) to Flight 3's arrival (11:00 p.m.) is 690 minutes (11 hours, 30 minutes) — a number we computed by hand from the given times, not one stated by the official prompt.

Common Mistakes to Avoid

  • Looping with the wrong bound, such as i < flights.size(), which would let flights.get(i + 1) run past the end of the list on the final iteration.
  • Starting shortest at 0. A layover can never legitimately be 0 or negative here, but seeding with 0 would make the if (layover < shortest) check never true, so the method would incorrectly always return 0.
  • Forgetting the fewer-than-two-flights case. Without it, flights.get(1) would throw an exception on a Trip with zero or one flight.
  • Calling minutesUntil on the wrong object (e.g., flights.get(i + 1).getDepartureTime().minutesUntil(flights.get(i).getArrivalTime())), which would compute the layover as a negative number instead of positive.

Notes: A Method Not on the AP CSA Quick Reference Sheet

Math.min would let the comparison in part (b) collapse into a single line:

public int getShortestLayover()
{
    if (flights.size() < 2)
    {
        return -1;
    }

    int shortest = flights.get(0).getArrivalTime().minutesUntil(flights.get(1).getDepartureTime());

    for (int i = 1; i < flights.size() - 1; i++)
    {
        int layover = flights.get(i).getArrivalTime().minutesUntil(flights.get(i + 1).getDepartureTime());
        shortest = Math.min(shortest, layover);
    }

    return shortest;
}
  • Math.min isn't listed on the real exam's Java Quick Reference sheet — only Math.abs, Math.pow, Math.sqrt, and Math.random are. That doesn't mean it's off-limits; AP CSA graders accept any correct Java, whether or not it happens to appear on that sheet.
  • What the sheet actually guarantees is that those specific methods are printed for you to look up during the exam if you blank on the exact signature. Math.min is completely safe to use if you're confident in it — the if version above is simply the one that doesn't depend on remembering it.

Key Takeaways

  • Special cases (an empty list, a list too short for the operation being asked) belong in a check at the very top of the method, before any indexing into the list happens.
  • "Compare every consecutive pair" is a loop pattern where the loop bound has to leave room for looking one element ahead — i < list.size() - 1, not i < list.size().
  • Seeding a running "best so far" value with an actual computed value from the data (rather than a guessed sentinel like 0) sidesteps having to reason about whether that sentinel is actually safe.

Related FRQs