目录
1. 力扣链接
3140. 连续空余座位 II - 力扣(LeetCode)
2. 经典例题
表:
Cinema
+-------------+------+ | Column Name | Type | +-------------+------+ | seat_id | int | | free | bool | +-------------+------+ seat_id 是这张表中的自增列。 这张表的每一行表示第 i 个作为是否空余。1 表示空余,而 0 表示被占用。编写一个解决方案来找到电影院中 最长的空余座位 的 长度。
注意:
- 保证 最多有一个 最长连续序列。
- 如果有 多个 相同长度 的连续序列,将它们全部输出。
返回结果表以
first_seat_id
升序排序。结果表的格式如下所示。
示例:
输入:
Cinema 表:
+---------+------+ | seat_id | free | +---------+------+ | 1 | 1 | | 2 | 0 | | 3 | 1 | | 4 | 1 | | 5 | 1 | +---------+------+输出:
+-----------------+----------------+-----------------------+ | first_seat_id | last_seat_id | consecutive_seats_len | +-----------------+----------------+-----------------------+ | 3 | 5 | 3 | +-----------------+----------------+-----------------------+解释:
- 可用座位的最长连续序列从座位 3 开始,到座位 5 结束,长度为 3。
输出表以 first_seat_id 升序排序。
-- 建表语句
CREATE TABLE if Not exists Cinema (
seat_id INT PRIMARY KEY AUTO_INCREMENT,
free BOOLEAN
);
Truncate table Cinema;
insert into Cinema (seat_id, free) values ('1', '1');
insert into Cinema (seat_id, free) values ('2', '0');
insert into Cinema (seat_id, free) values ('3', '1');
insert into Cinema (seat_id, free) values ('4', '1');
insert into Cinema (seat_id, free) values ('5', '1');
3. 分析
- 题目求连续空余座位,先用where条件过滤出空余座位
- 等差数列定义:一个数列中,任意相邻两项的差是一个常数,这个常数称为公差。
- 如果两个等差数列的公差相同,那么它们的差值也是等差数列,且公差相同。所以,当两个等差数列的差一致时,它们的差值也是一个等差数列,且公差相同。如果这个公差为 0,那么它们的差值是一个常数数列,可以认为是连续的。
- 等差数列1 seat_id 作为第一个公差为1的等差数列, 等差数列2 根据seat_id进行row_number排名 作为第二个公差为1的等差数列。
- 等差数列1 - 等差数列2 求差值
- 相同的差值则认为连续的,因此根据差值进行分组
- 使用聚合函数count、min、max分别求连续的个数、连续开始值,连续结束值
- (假如需求是求连续N个的座位,则直接可以使用where对分组后count(*)进行条件过滤)
- 题目求最长连续空余座位,而且如果多个相同长度的连续,则全部输出,可以分析要对连续个数进行排名,并且我们要用dense_rank进行对长度倒序排名
- 对排名后的数据使用where进行条件过滤,得出排名为1的数据,按照连续开始值进行升序排序输出
4. 代码实现
with t1 as(
select
*,
-- 等差数列2
row_number() over(order by seat_id) rn,
-- 等差数列1 - 等差数列2
seat_id - row_number() over(order by seat_id) diff
from Cinema where free = 1
),t2 as(
select
-- 连续开始id
min(seat_id) first_seat_id,
-- 连续结束id
max(seat_id) last_seat_id,
-- 连续个数(长度)
count(*) consecutive_seats_len,
-- 对连续长度倒序排序
dense_rank() over(order by count(*) desc) rn
from t1
group by diff
)select
first_seat_id,
last_seat_id,
consecutive_seats_len
from t2
where rn = 1
order by first_seat_id;
5. 代码验证
6. 类似题目练习
1285. 找到连续区间的开始和结束数字 - 力扣(LeetCode)
7. 总结
- 熟练使用where条件过滤
- 了解等差数列的定义
- 熟练找出表中两个公差相等的等差数列
- 熟练使用不同的排名函数
- 熟练使用group by分组
- 熟练使用聚合函数
- 熟练使用order by排序