【LeetCode 题解】数据库:626.换座位
一、问题剖析
在数据库的实际应用中,我们常常会遇到需要对表中的数据进行各种变换和处理的情况。本题给定了一个名为 Seat
的表,它包含学生的 id
和 student
两列信息,其中 id
是主键且为连续的正整数。我们的任务是编写一个 SQL 解决方案,实现每两个连续学生座位号的交换,并且如果学生数量为奇数,最后一个学生的 id
保持不变,最后按 id
升序返回结果表。
二、解题思路探索
常规思路:条件判断与更新
我们可以通过对 id
的奇偶性进行判断来实现座位交换。对于偶数 id
的学生,将其与前一个(奇数 id
)学生的座位进行交换;对于奇数 id
的学生,将其与后一个(偶数 id
)学生的座位进行交换。但由于我们不能直接修改原表的 id
列(id
是主键,通常不允许随意修改),所以我们可以考虑使用 CASE WHEN
语句来构造新的 id
和 student
组合。
具体实现步骤
-
对于
id
为偶数的行,我们希望将其student
与id - 1
的学生进行交换,即新的student
为(SELECT student FROM Seat WHERE id = s.id - 1)
。 -
对于
id
为奇数且不是最后一行(即id < (SELECT MAX(id) FROM Seat)
)的行,我们希望将其student
与id + 1
的学生进行交换,即新的student
为(SELECT student FROM Seat WHERE id = s.id + 1)
。 -
对于
id
为奇数且是最后一行(即id = (SELECT MAX(id) FROM Seat)
)的行,其student
保持不变。
三、SQL 代码实现
SELECT
CASE
-- id为偶数时
WHEN id % 2 = 0 THEN (SELECT student FROM Seat WHERE id = s.id - 1)
-- id为奇数且不是最后一行时
WHEN id < (SELECT MAX(id) FROM Seat) THEN (SELECT student FROM Seat WHERE id = s.id + 1)
-- id为奇数且是最后一行时
ELSE student
END AS student,
id
FROM
Seat s
ORDER BY
id;
四、代码详细解析
1、CASE WHEN
语句:
CASE
-- id为偶数时
WHEN id % 2 = 0 THEN (SELECT student FROM Seat WHERE id = s.id - 1)
-- id为奇数且不是最后一行时
WHEN id < (SELECT MAX(id) FROM Seat) THEN (SELECT student FROM Seat WHERE id = s.id + 1)
-- id为奇数且是最后一行时
ELSE student
END AS student,
-
WHEN id % 2 = 0 THEN (SELECT student FROM Seat WHERE id = s.id - 1)
:当id
除以 2 的余数为 0,即id
为偶数时,通过子查询从Seat
表中获取id - 1
的学生姓名,实现与前一个学生的座位交换。 -
WHEN id < (SELECT MAX(id) FROM Seat) THEN (SELECT student FROM Seat WHERE id = s.id + 1)
:当id
为奇数且小于表中的最大id
时,通过子查询从Seat
表中获取id + 1
的学生姓名,实现与后一个学生的座位交换。 -
ELSE student
:当id
为奇数且等于表中的最大id
时,即最后一个学生,其student
保持不变。
2、选择 id
列:
id
在结果中选择 id
列,因为我们最终需要按 id
升序返回结果表,并且 id
列在交换座位的逻辑中起到了关键的判断作用。
3、排序:
ORDER BY
id;
使用 ORDER BY
子句按照 id
升序对结果进行排序,确保结果表符合题目要求。
五、复杂度分析
-
时间复杂度:对于每一行数据,我们都进行了条件判断和可能的子查询操作。由于子查询需要在
Seat
表中查找特定id
的记录,而查找操作的时间复杂度与表的大小有关。假设Seat
表有n
条记录,对于每一行数据的操作时间复杂度为 (O(1))(不考虑子查询),而子查询的时间复杂度为 (O(n))(在最坏情况下需要遍历整个表)。因此,总的时间复杂度为 (O(n^2))。但在实际情况中,如果id
列上有索引,子查询的效率会大大提高,时间复杂度会接近 (O(n))。 -
空间复杂度:我们在查询过程中没有使用额外的与数据规模相关的空间,只是对表中的数据进行了读取和处理,因此空间复杂度为 (O(1))。
六、测试用例验证
1、输入数据:
-- 插入示例数据
INSERT INTO Seat (id, student) VALUES
(1, 'Abbot'),
(2, 'Doris'),
(3, 'Emerson'),
(4, 'Green'),
(5, 'Jeames');
2、预期输出:
+----+---------+
| id | student |
+----+---------+
| 1 | Doris |
| 2 | Abbot |
| 3 | Green |
| 4 | Emerson |
| 5 | Jeames |
+----+---------+
3、验证过程:
将上述 SQL 代码在数据库中运行,将得到的结果与预期输出进行对比,如果结果一致,则说明我们的代码实现是正确的。
七、总结
通过解决 “换座位” 这一问题,我们深入学习了如何利用 CASE WHEN
语句和子查询来实现数据的变换和处理。在处理类似需要对表中数据进行特定逻辑变换的问题时,我们要善于分析数据的特点和规律,合理运用 SQL 的各种语句和函数。同时,对于时间复杂度和空间复杂度的分析也有助于我们评估代码的性能,在实际应用中选择更优的解决方案。希望大家通过这篇博客对 SQL 的应用有更深入的理解和掌握。
感谢各位的阅读,后续将持续给大家讲解力扣中的算法题和数据库题,如果觉得这篇内容对你有帮助,别忘了点赞和关注,后续还有更多精彩的算法解析与你分享!