LeetCode 1109 - Corporate Flight Bookings
The problem is asking us to compute the total number of seats reserved for each flight given a list of flight bookings. Each booking specifies a range of consecutive flights [firsti, lasti] and the number of seats seatsi reserved for each flight in that range.
Difficulty: 🟡 Medium
Topics: Array, Prefix Sum
Solution
Problem Understanding
The problem is asking us to compute the total number of seats reserved for each flight given a list of flight bookings. Each booking specifies a range of consecutive flights [firsti, lasti] and the number of seats seatsi reserved for each flight in that range. The flights are numbered from 1 to n, and the result should be an array answer of length n, where answer[i] represents the total seats booked for flight i+1.
The input bookings can be thought of as a set of "range updates": each booking adds a fixed number of seats to a contiguous range of flights. The challenge is to efficiently process multiple overlapping bookings without iterating through every flight in every booking, which could be too slow for large inputs.
Constraints tell us that n and bookings.length can be up to 20,000, so a naive solution that iterates over the flights for every booking could reach 400 million operations, which is too slow. The input guarantees that all indices are valid (1 <= firsti <= lasti <= n) and the number of seats is always positive, so we do not have to handle invalid bookings or negative values.
Important edge cases include bookings that cover a single flight, bookings that cover the entire range of flights, multiple overlapping bookings, and bookings that start or end at the boundary flights.
Approaches
The brute-force approach iterates over each booking and updates the number of seats for every flight in the specified range. This guarantees correctness because it directly applies the seat reservations, but it is inefficient. For each booking [first, last, seats], it performs (last - first + 1) operations. In the worst case, this leads to a time complexity of O(n * m), where m is the number of bookings, which can be up to 400 million operations for maximum input sizes.
The optimal approach leverages the prefix sum trick, a common technique for efficiently applying range updates. Instead of updating every element in the range for each booking, we mark the start of the range with +seatsi and the position after the end of the range with -seatsi. After processing all bookings, a single prefix sum pass converts these markers into the total seats for each flight. This reduces the time complexity to O(n + m), which is feasible for the given constraints.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n * m) | O(n) | Directly updates each flight in every booking range |
| Optimal | O(n + m) | O(n) | Uses prefix sum technique to apply range updates efficiently |
Algorithm Walkthrough
- Initialize an array
resof lengthnwith all zeros. This array will eventually hold the total seats for each flight. - Iterate over each booking
[first, last, seats]inbookings. For each booking, incrementres[first-1]byseatsto mark the start of the booking range. Iflast < n, decrementres[last]byseatsto mark the end of the booking range. - After all bookings have been processed, iterate through
resfrom index1ton-1, updating each element to be the sum of itself and the previous element. This computes the prefix sum, converting the range markers into actual seat totals. - Return the final
resarray.
Why it works: The +seatsi at the start index and -seatsi after the end index create a difference array. Applying the prefix sum ensures that all flights in the range [first, last] accumulate seatsi, while flights outside the range remain unaffected. This guarantees correctness while reducing unnecessary updates.
Python Solution
from typing import List
class Solution:
def corpFlightBookings(self, bookings: List[List[int]], n: int) -> List[int]:
res = [0] * n
for first, last, seats in bookings:
res[first - 1] += seats
if last < n:
res[last] -= seats
for i in range(1, n):
res[i] += res[i - 1]
return res
The Python implementation first initializes a zero array for all flights. It then processes each booking by marking the start and end of the booking in the array. The prefix sum loop propagates the seat counts across the ranges efficiently, producing the final result.
Go Solution
func corpFlightBookings(bookings [][]int, n int) []int {
res := make([]int, n)
for _, booking := range bookings {
first, last, seats := booking[0], booking[1], booking[2]
res[first-1] += seats
if last < n {
res[last] -= seats
}
}
for i := 1; i < n; i++ {
res[i] += res[i-1]
}
return res
}
In Go, we initialize a slice res of length n. The approach mirrors Python: we apply the difference array technique and then a prefix sum. Go requires explicit slice creation and integer indexing, but the logic remains the same. There is no need to handle nil because make([]int, n) always returns a properly sized slice.
Worked Examples
Example 1: bookings = [[1,2,10],[2,3,20],[2,5,25]], n = 5
| Step | Action | res Array |
|---|---|---|
| Init | res = [0,0,0,0,0] |
[0,0,0,0,0] |
| Booking 1 | add 10 to res[0], subtract 10 from res[2] | [10,0,-10,0,0] |
| Booking 2 | add 20 to res[1], subtract 20 from res[3] | [10,20,-10,-20,0] |
| Booking 3 | add 25 to res[1], subtract 25 from res[5] (ignored) | [10,45,-10,-20,0] |
| Prefix sum | compute cumulative sums | [10,55,45,25,25] |
Example 2: bookings = [[1,2,10],[2,2,15]], n = 2
| Step | Action | res Array |
|---|---|---|
| Init | [0,0] |
[0,0] |
| Booking 1 | add 10 to res[0], subtract 10 from res[2] (ignored) | [10,0] |
| Booking 2 | add 15 to res[1], subtract 15 from res[2] (ignored) | [10,15] |
| Prefix sum | [10,25] |
[10,25] |
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n + m) | We process each booking once (O(m)) and compute prefix sums once (O(n)) |
| Space | O(n) | We store one array of length n for the result |
The optimal solution is linear in both the number of flights and the number of bookings, making it suitable for large input sizes up to 20,000.
Test Cases
# Provided examples
assert Solution().corpFlightBookings([[1,2,10],[2,3,20],[2,5,25]], 5) == [10,55,45,25,25] # Example 1
assert Solution().corpFlightBookings([[1,2,10],[2,2,15]], 2) == [10,25] # Example 2
# Edge cases
assert Solution().corpFlightBookings([[1,1,5]], 1) == [5] # Single flight
assert Solution().corpFlightBookings([[1,5,1]], 5) == [1,1,1,1,1] # Full range booking
assert Solution().corpFlightBookings([[1,3,10],[2,5,5],[3,3,2]], 5) == [10,15,17,5,5] # Multiple overlaps
assert Solution().corpFlightBookings([], 3) == [0,0,0] # No bookings
assert Solution().corpFlightBookings([[2,2,10]], 5) == [0,10,0,0,0] # Single flight in the middle
| Test | Why |
|---|---|
| Example 1 | Standard case with overlapping ranges |
| Example 2 | Small input with overlapping bookings on a single flight |
| Single flight | Minimal input size |
| Full range booking | Booking covers all flights |
| Multiple overlaps | Tests correct aggregation of overlapping bookings |
| No bookings | Edge case, should return all zeros |
| Single middle flight | Booking not at boundaries |
Edge Cases
One edge case is a booking that covers only the first flight. This tests whether the implementation correctly handles array indexing at the start. The algorithm adds the seat count to the first element and handles the prefix sum properly.
Another edge case is a booking that covers the last flight. This tests whether we correctly avoid subtracting beyond the array bounds. Our implementation checks if last < n before decrementing, ensuring safety.
A third edge case is multiple overlapping bookings that cover the