力扣题
1、题目地址
571. 给定数字的频率查询中位数
2、模拟表
Numbers 表:
Column Name | Type |
---|---|
num | int |
frequency | int |
- num 是这张表的主键(具有唯一值的列)。
- 这张表的每一行表示某个数字在该数据库中的出现频率。
3、要求
中位数 是将数据样本中半数较高值和半数较低值分隔开的值。
编写解决方案,解压 Numbers 表,报告数据库中所有数字的 中位数 。
结果四舍五入至 一位小数 。
4、示例
输入:
Numbers 表:
num | frequency |
---|---|
0 | 7 |
1 | 1 |
2 | 3 |
3 | 1 |
输出:
median |
---|
0.0 |
解释:
如果解压这个 Numbers 表,可以得到 [0, 0, 0, 0, 0, 0, 0, 1, 2, 2, 2, 3] ,所以中位数是 (0 + 0) / 2 = 0 。
5、代码编写
我的代码
我的思路:
1、计算总出现多少次数(tmp),示例12次
2、根据是奇数次数(tmp2)或偶数次数(tmp3)拿到对应的位置值(tmp4),示例里偶数(12),拿到6和7
3、累加数字出现次数(tmp5)(7-8-11-12),可以用做范围用
4、位置值(tmp4)和累加数字出现次数(tmp5),控制 tmp4 小于 tmp5 再去取最小值即可,里面需要对位置值(tmp4)进行分组的原因是可能取出的 tmp5 不一样(奇数取到的就一定只有一个,但偶数可能取到两个的情况)
5、将最小值取出并去重,可能偶数取出两个相同的情况,然后再去累加数字出现次数(tmp5)查询即可,记得要求说要保留一位小数
with tmp as (select sum(frequency) as numfrom Numbers
), tmp2 as (select ceil(num/2) as numfrom tmpwhere mod(num, 2) = 1
), tmp3 as (select num/2 as numfrom tmpwhere mod(num, 2) = 0union allselect num/2+1 as numfrom tmpwhere mod(num, 2) = 0
), tmp4 as (select * from tmp2union allselect * from tmp3
), tmp5 as (select num, sum(frequency) over(order by num) as numRangefrom Numbers
)
select round(avg(num), 1) AS median
from tmp5
where numRange in (select distinct numRangefrom (select one.num, min(two.numRange) AS numRangefrom tmp4 oneleft join tmp5 two on one.num <= two.numRangegroup by one.num) AS one
)
网友代码(巧妙)
思路:新增两列,将从后往前和从前往后的频数相加,两个数都需要大于等于总数一半,再取平均
with tmp as (select num, frequency,sum(frequency) over(order by num asc) as total,sum(frequency) over(order by num desc) as total1from Numbers
)
select avg(num) as median
from tmp
where total>=(select sum(frequency) from Numbers)/2
and total1>=(select sum(frequency) from Numbers)/2