活动参与者:既不是最多也不是最少
LeetCode 1355 · 分组计数、双向排名、排除极值
面试怎么回答
按活动计数,再用 RANK() OVER (ORDER BY cnt) 和 RANK() OVER (ORDER BY cnt DESC) 两个排名,两者都不为 1 的保留。也可以写成 cnt NOT IN (最大值, 最小值)。如果可能有零参与的活动,要先用活动表左关联补上 0。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
题意
朋友表记录每个人参加的活动,活动表是活动清单。找出参与人数既不是最多、也不是最少的活动。
表结构
- Friends:id(主键)、name、activity
- Activities:id(主键)、name
思路
按活动计数后,同时做升序和降序两个排名,两个排名都不是 1 的活动就是答案。也可以先求出最大和最小人数,再排除等于它们的活动。题目保证每个活动至少一人参加,所以不需要关联活动表。
参考解法
select activity
from (
select activity,
rank()over(order by cnt) rk1,
rank()over(order by cnt desc) rk2
from
(
select activity ,count(*) cnt
from Friends
group by activity
)t1
)t2
where rk1 !=1 and rk2 != 1
易错点
- 并列最多或并列最少的活动都要排除,用 RANK 而不是 ROW_NUMBER。
- 如果存在没人参加的活动,它才是真正的「最少」,这时必须以活动表为主表 LEFT JOIN 计数。