Table: Queue
+-------------+---------+ | Column Name | Type | +-------------+---------+ | person_id | int | | person_name | varchar | | weight | int | | turn | int | +-------------+---------+ person_id column contains unique values. This table has the information about all people waiting for a bus. The person_id and turn columns will contain all numbers from 1 to n, where n is the number of rows in the table. turn determines the order of which the people will board the bus, where turn=1 denotes the first person to board and turn=n denotes the last person to board. weight is the weight of the person in kilograms.
There is a queue of people waiting to board a bus. However, the bus has a weight limit of 1000
kilograms, so there may be some people who cannot board.
Write a solution to find the person_name
of the last person that can fit on the bus without exceeding the weight limit. The test cases are generated such that the first person does not exceed the weight limit.
Note that only one person can board the bus at any given turn.
The result format is in the following example.
Example 1:
Input: Queue table: +-----------+-------------+--------+------+ | person_id | person_name | weight | turn | +-----------+-------------+--------+------+ | 5 | Alice | 250 | 1 | | 4 | Bob | 175 | 5 | | 3 | Alex | 350 | 2 | | 6 | John Cena | 400 | 3 | | 1 | Winston | 500 | 6 | | 2 | Marie | 200 | 4 | +-----------+-------------+--------+------+ Output: +-------------+ | person_name | +-------------+ | John Cena | +-------------+ Explanation: The folowing table is ordered by the turn for simplicity. +------+----+-----------+--------+--------------+ | Turn | ID | Name | Weight | Total Weight | +------+----+-----------+--------+--------------+ | 1 | 5 | Alice | 250 | 250 | | 2 | 3 | Alex | 350 | 600 | | 3 | 6 | John Cena | 400 | 1000 | (last person to board) | 4 | 2 | Marie | 200 | 1200 | (cannot board) | 5 | 4 | Bob | 175 | ___ | | 6 | 1 | Winston | 500 | ___ | +------+----+-----------+--------+--------------+
The problem requires finding the name of the last person who can board a bus with a weight limit of 1000 kg. The input is a Queue
table containing information about people waiting to board, including their ID, name, weight, and boarding order (turn
).
Two SQL solutions are provided, both leveraging the power of SQL window functions and aggregation. Let's analyze each:
This approach uses a self-join to calculate the cumulative weight up to each person's turn.
Code (MySQL):
SELECT a.person_name
FROM
Queue AS a,
Queue AS b
WHERE a.turn >= b.turn
GROUP BY a.person_id
HAVING SUM(b.weight) <= 1000
ORDER BY a.turn DESC
LIMIT 1;
Explanation:
Self-Join: The query performs a self-join of the Queue
table (aliased as a
and b
). The WHERE a.turn >= b.turn
clause ensures that for each person (a
), we sum the weights of all people with turns less than or equal to that person's turn.
Grouping and Aggregation: GROUP BY a.person_id
groups the results by each person. SUM(b.weight)
calculates the cumulative weight for each person's group.
Filtering: HAVING SUM(b.weight) <= 1000
filters out groups whose cumulative weight exceeds the limit.
Ordering and Limiting: ORDER BY a.turn DESC
orders the results by turn in descending order (latest turn first). LIMIT 1
selects only the top result—the last person who fits.
Time Complexity: The self-join dominates the complexity, making it O(N^2) in the worst case, where N is the number of people in the queue. This is because for each person, the query sums the weights of all preceding people.
Space Complexity: The space complexity depends on the size of the intermediate result set generated by the join and aggregation. In the worst case, it could be O(N).
This solution uses a window function to efficiently calculate the cumulative weight. It is significantly more efficient than the self-join approach.
Code (MySQL):
WITH
T AS (
SELECT
person_name,
SUM(weight) OVER (ORDER BY turn) AS s
FROM Queue
)
SELECT person_name
FROM T
WHERE s <= 1000
ORDER BY s DESC
LIMIT 1;
Explanation:
Common Table Expression (CTE): A CTE named T
is created to calculate the cumulative sum using the SUM() OVER (ORDER BY turn)
window function. This efficiently computes the running total of weights ordered by the turn
column.
Filtering and Ordering: The main query selects person_name
from T
, filters for rows where the cumulative sum (s
) is less than or equal to 1000, orders the result in descending order of cumulative sum, and limits the result to the first row.
Time Complexity: This solution is significantly faster, with a time complexity of O(N), where N is the number of people in the queue. This is because the window function calculates the cumulative sum in a single pass.
Space Complexity: The space complexity is O(N) for storing the intermediate results in the CTE, but this is generally more efficient than the self-join's space usage in practice.
Solution 2 using the window function is the preferred and significantly more efficient approach due to its linear time complexity compared to the quadratic complexity of Solution 1. It leverages the optimized capabilities of SQL databases to handle cumulative calculations effectively.