首页 技术 正文
技术 2022年11月14日
0 收藏 741 点赞 2,846 浏览 1860 个字

题目链接:https://leetcode-cn.com/problems/consecutive-numbers/

题目

编写一个 SQL 查询,查找所有至少连续出现三次的数字。

+—-+—–+

| Id | Num |

+—-+—–+

| 1 | 1 |

| 2 | 1 |

| 3 | 1 |

| 4 | 2 |

| 5 | 1 |

| 6 | 2 |

| 7 | 2 |

+—-+—–+

例如,给定上面的 Logs 表, 1 是唯一连续出现至少三次的数字。

+—————–+

| ConsecutiveNums |

+—————–+

| 1 |

+—————–+

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/consecutive-numbers

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解答

先总结方法:

  1. 使用自连接,3个表连接;(如果连续出现1000次,这个方法就不行了。。)
  2. 使用 oracle 窗口函数;
  3. 使用 MySQL 变量的方式;

一开始看的时候,毫无头绪。。

解法一

粗略的看了下解答,用自连接的方法,尝试了下,居然通过了。

---- oracle ----
/* Write your PL/SQL query statement below */
select distinct a.Num as ConsecutiveNums
from Logs a,
Logs b,
Logs c
where a.Id = b.Id + 1
and a.Id = c.Id + 2
and a.Num = b.Num
and a.Num = c.Num --- 806ms

考虑如果 id 不连续出现的情况,则需要在数据表中插入一列新的 id 自增数据进行标识。

解法二

  1. 由于要获取至少连续3次出现的数字,看到这个题肯定是会变的,如果是至少连续出现4次(100次),连接4个表(连接1000个)?这种方法肯定是不可取的。

  2. 找规律,找出这连续起来的数字有什么规律呢?发现连续的数字是相同的数字,但是id有可能不是连续的,我们就需要通过对结果集进行再次编号,让其变成连续的。

  3. 首先我们获取到对每条数据编号从1开始使用 row_number() 函数使用 id 来排序。

  4. 然后我们通过另一种方式排序将这些 num 值一样的进行排序,然后对其编号同样使用 row_bumber() 使用 num 来分组使用 id 排序 over(partition by num order by id)

  5. 通过3、4步骤,两个相减之后我们可以得到,只要是相等的,则相减的值是一样的。而且如果不连续的话相减值也不一样。

  6. 最后再通过 numrn 两个共同分组找到一样的一共有几个,就可以找到连续的了。

最终代码为:

---- oracle ----
/* Write your PL/SQL query statement below */
select distinct Num as ConsecutiveNums
from
(
select Num,
rn,
count(Id) as cnt
from
(
select Id,
Num,
row_number() over(order by id) - row_number() over(partition by num order by id) as rn
from Logs
)
group by Num, rn
)
where cnt >= 3; ---- 1414ms 好慢

想了想,会不会存在 Num + rn 误判的情况?因为一直递增,貌似不会。

解法三

使用2个变量进行统计。

---- MySQL ----
select distinct t.Num as ConsecutiveNums
from
(
select a.Num,
@cnt := if(@pre = a.Num, @cnt + 1, 1) cnt,
@pre := a.Num pre
from Logs a,
(select @pre := null,
@cnt := 0) b
) t
where t.cnt >= 3; ---- 179ms

判断当前Num与上一个Num是否一致,如果是cnt加一,如果不是,重新计数。

高明!

思考

联想到以前自己的一个奇思妙想:赌钱!押大还是押小,买定离手!

  1. 买1块钱大,赢了的话,继续买;
  2. 输了的话,买2块钱大;
  3. 赢了的话,恢复买1块,输了的话,买4块钱大;
  4. 以此循环
  5. 设定上限,直到128块就认输,止损。

当时想到这个做法的时候,问自己,如果我有较多的资金的话,假设我有1w,那一直买,买到8192的时候,已经是2的13次方了。。不可能连续输了13次吧。。当时这么想。。

后来,觉得连续开13次小还是有概率的,想用程序随机模拟一下输赢的概率。。但是拖延症上身,一直没有去实践。。

今天这道题,尝试一下吧。。

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,966
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,487
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,332
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,115
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,748
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,783