LeetCode 626 - Exchange Seats
This problem asks us to swap the seat IDs of every two consecutive students in a classroom. The input is a table called Seat with two columns: id, which is a unique integer representing the seat number, and student, which is a string representing the student's name.
Difficulty: 🟡 Medium
Topics: Database
Solution
Problem Understanding
This problem asks us to swap the seat IDs of every two consecutive students in a classroom. The input is a table called Seat with two columns: id, which is a unique integer representing the seat number, and student, which is a string representing the student's name. The IDs are consecutive integers starting from 1, which guarantees there are no gaps in the sequence. The output is the same table, but with the IDs of every two consecutive students swapped. If the total number of students is odd, the last student remains in their original seat.
In other words, for every pair (i, i+1), we swap the students' positions. This is purely a reordering problem based on the sequential IDs. Important edge cases include when there are no students (empty table), only one student (no swap occurs), or an odd number of students (the last one remains in place).
The constraints are mild since the table uses consecutive IDs starting from 1. We do not have to worry about gaps or invalid IDs, and there are no constraints about very large inputs because SQL handles large datasets efficiently with simple updates.
Approaches
A brute-force approach would involve manually updating the table row by row. We could fetch all the rows, iterate through them in pairs, and swap the IDs by issuing multiple UPDATE statements. While this approach works and produces the correct output, it is inefficient because it requires multiple database writes and does not scale well for large tables.
The key insight for an optimal SQL solution is that we do not need to iterate row by row. Since IDs are consecutive, we can compute the swapped ID using a simple formula: if id is even, the new ID becomes id - 1; if id is odd, the new ID becomes id + 1. For the last row in an odd-numbered table, the swap automatically does not apply because there is no consecutive pair. This allows us to perform the swap in a single SQL query using CASE WHEN logic.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n) | O(n) | Fetch all rows, swap IDs pairwise using multiple updates |
| Optimal | O(n) | O(1) | Single SQL query with conditional logic to swap consecutive IDs |
Algorithm Walkthrough
- Select all columns from the
Seattable. We need bothidandstudentto construct the result. - Use a
CASEstatement to compute the new ID for each row. For even IDs, subtract 1 to swap with the previous student. For odd IDs, add 1 to swap with the next student. - Ensure that the last student is not swapped if the number of rows is odd. Since IDs are consecutive, swapping odd IDs naturally moves the last student beyond the table, which is handled implicitly.
- Order the result by the newly computed
idin ascending order to return the final swapped seating arrangement.
Why it works: The algorithm leverages the consecutive nature of IDs. By incrementing odd IDs and decrementing even IDs, every consecutive pair is swapped exactly once, and any unmatched last ID remains untouched. Sorting by the computed ID restores the correct sequential order.
Python Solution
# This problem is SQL-based; Python solution is not typical for direct submission,
# but we can demonstrate the logic with a Pandas approach for conceptual understanding.
import pandas as pd
def swapSeats(seat: pd.DataFrame) -> pd.DataFrame:
seat = seat.copy()
seat['new_id'] = seat['id'].apply(lambda x: x + 1 if x % 2 != 0 else x - 1)
# If the number of rows is odd, last row's new_id should remain the same
if len(seat) % 2 != 0:
seat.loc[seat['id'].idxmax(), 'new_id'] = seat['id'].max()
return seat.sort_values('new_id').drop(columns='new_id').reset_index(drop=True)
This Python solution mirrors the SQL logic. It computes the new IDs using apply and a lambda function, adjusts the last row if necessary, and finally sorts by the new IDs to produce the final order.
Go Solution
// This problem is SQL-based, but we can demonstrate the logic in Go with slices
package main
import (
"fmt"
"sort"
)
type Seat struct {
Id int
Student string
}
func swapSeats(seats []Seat) []Seat {
n := len(seats)
newSeats := make([]Seat, n)
copy(newSeats, seats)
for i := 0; i+1 < n; i += 2 {
newSeats[i], newSeats[i+1] = newSeats[i+1], newSeats[i]
}
return newSeats
}
func main() {
seats := []Seat{
{1, "Abbot"}, {2, "Doris"}, {3, "Emerson"}, {4, "Green"}, {5, "Jeames"},
}
swapped := swapSeats(seats)
sort.Slice(swapped, func(i, j int) bool { return swapped[i].Id < swapped[j].Id })
fmt.Println(swapped)
}
The Go version uses a slice of structs to represent the table. Swapping occurs in-place for every pair of consecutive elements. The sort ensures the result remains ordered by the original IDs, similar to SQL ordering.
Worked Examples
Example:
Input table:
| id | student |
|---|---|
| 1 | Abbot |
| 2 | Doris |
| 3 | Emerson |
| 4 | Green |
| 5 | Jeames |
Step-by-step:
- Compute new IDs:
| id | new_id | student |
|---|---|---|
| 1 | 2 | Abbot |
| 2 | 1 | Doris |
| 3 | 4 | Emerson |
| 4 | 3 | Green |
| 5 | 5 | Jeames |
- Sort by
new_id:
| id | student |
|---|---|
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | Jeames |
The last student is not moved because the number of students is odd.
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Each row is processed once to compute the new ID |
| Space | O(1) | Only the output table is created; no extra storage is required beyond the table |
The complexity is linear because we only iterate over the table once. Memory usage is minimal as we do not require additional data structures beyond a temporary copy of the table.
Test Cases
import pandas as pd
# test cases
assert swapSeats(pd.DataFrame([])).empty # empty table
assert swapSeats(pd.DataFrame({'id':[1], 'student':['Abbot']})).iloc[0]['student'] == 'Abbot' # single row
assert swapSeats(pd.DataFrame({'id':[1,2], 'student':['Abbot','Doris']})).iloc[0]['student'] == 'Doris' # 2 rows
assert swapSeats(pd.DataFrame({'id':[1,2,3,4,5], 'student':['Abbot','Doris','Emerson','Green','Jeames']})).iloc[4]['student'] == 'Jeames' # odd number
assert swapSeats(pd.DataFrame({'id':[1,2,3,4], 'student':['A','B','C','D']})).iloc[0]['student'] == 'B' # even number
| Test | Why |
|---|---|
| empty table | verifies function handles no input |
| single row | last student is unchanged |
| two rows | basic swap works |
| odd number of rows | last row remains |
| even number of rows | all pairs swapped correctly |
Edge Cases
An empty table is a potential source of errors because attempting to access elements may cause index errors. Our implementation handles this by returning an empty table without modification.
A table with a single student could be mishandled if the swap logic does not check the pair bounds. The algorithm naturally handles this because no pair exists for swapping, so the student's seat remains the same.
A table with an odd number of students could cause an off-by-one error if the last student is included in a pair. By computing new IDs conditionally and leaving the last student untouched, the implementation ensures the correct behavior.
This design guarantees correctness for all boundary scenarios.