Leetcode-2021刷题记录

180. 连续出现的数字

题目链接:180. 连续出现的数字

1. 思路

  • 题目给出的表中有连续的Id和无序Num,这种情况下连续出现的数字对应的Id也将是连续增加的,因此只需要判断对应的id是否连续递增即可
  • 如果题目没给出id,可以用ROW_NUMBER()1开窗函数给Num标记连续递增的id

2. 实现方法

  • 对原表Logs进行开窗,经过对Num的分区和排序后,现在生成了一个Num从小到大排序,且相同Num值为一个窗口标记连续递增的正数,我将这一列命名为orders
ROW_NUMBER() 
Over(Partition by Num Order by Num) 
as orders
  • 例如题目中给出的案例经过这一步后会得到下表
  • 该表就可以很快看出,id连续时,orders也会连续,因此问题又转化为寻找id和orders都连续超过3行以上的Num
idNumorders
111
212
313
514
421
  • 由于这两列递增的步长一致,因此,orders - id as minus的值在orders和id都连续时,会得到一列相同的差值,那么就只需要计数差值count(1) group by minus,这个值大于3对应的Num就是题目要求找出的Num

3. 完整代码

# Write your MySQL query statement below
Select distinct
    Num as ConsecutiveNums
From
(    Select
        Num
        ,(ranking - orders) as minus
        ,count(*) as cnt_same
    from
    (    Select *
            ,ROW_NUMBER() Over(Partition by Num Order by Num) as orders
        from(
            Select *
            ,ROW_NUMBER() Over() as ranking
            From Logs
        ) a 
    )b
    group by Num, minus
 )c
 Where cnt_same >= 3
;

在这里插入图片描述

4.同类拓展

  • 该题只要求连续3次以上的数,实际上一开始很快可以想到用LEAD()或者LAG()2函数直接解决这个问题,只需要移动两次Num列,使得每个id都能对应原本的Num以及下一行的Num、下两行的Num,这三个数都相等,那么就满足了>=3的条件,取出所有这样的Num即可
  • 但如果要求连续N次以上的数,那么上述原本就效率不高的解决方法就变得无法实现了,而3中给出的代码只需要将cnt_same字段设置为大于等于N就可以解除任意N值的同类题
  • 连续重复问题也可变体为连续大于,连续小于,或者连续满足任何条件,下面的第185题,也正是连续出现问题的一个变体形式

  1. ROW_NUMBER()会给窗口内的每一行分配一个唯一的数字,根据Order by内的排序规则对窗口内的数进行排序标记,用法:ROW_NUMBER() Over(Partition by 分区 Order by 排序) ↩︎

  2. LEAD()&LAG()函数:LEAD函数可以将指定列上移多行,LAG函数则将指定列下移多行,例如用LEAD函数可以取出每个月对应的下个月数据,LAG反之。用法:LEAD(指定列,偏移量[默认1],空值填充) Over(Partition by 分区 Order By 排序) ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值