连续问题通解

目录

1. 力扣链接

2. 经典例题

3. 分析

4. 代码实现

5. 代码验证

6. 类似题目练习

7. 总结


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. 分析

  1. 题目求连续空余座位,先用where条件过滤出空余座位
  2. 等差数列定义:一个数列中,任意相邻两项的差是一个常数,这个常数称为公差
  3. 如果两个等差数列的公差相同,那么它们的差值也是等差数列,且公差相同。所以,当两个等差数列的差一致时,它们的差值也是一个等差数列,且公差相同。如果这个公差为 0,那么它们的差值是一个常数数列,可以认为是连续的。
  4. 等差数列1 seat_id 作为第一个公差为1的等差数列, 等差数列2 根据seat_id进行row_number排名 作为第二个公差为1的等差数列。
  5. 等差数列1 - 等差数列2 求差值
  6. 相同的差值则认为连续的,因此根据差值进行分组
  7. 使用聚合函数count、min、max分别求连续的个数、连续开始值,连续结束值
  8. (假如需求是求连续N个的座位,则直接可以使用where对分组后count(*)进行条件过滤)
  9. 题目求最长连续空余座位,而且如果多个相同长度的连续,则全部输出,可以分析要对连续个数进行排名,并且我们要用dense_rank进行对长度倒序排名
  10. 对排名后的数据使用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. 类似题目练习

603. 连续空余座位 - 力扣(LeetCode)

601. 体育馆的人流量 - 力扣(LeetCode)

1285. 找到连续区间的开始和结束数字 - 力扣(LeetCode)

7. 总结

  • 熟练使用where条件过滤
  • 了解等差数列的定义
  • 熟练找出表中两个公差相等的等差数列
  • 熟练使用不同的排名函数
  • 熟练使用group by分组
  • 熟练使用聚合函数
  • 熟练使用order by排序

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码诗人i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值