这道题还是比较折磨人的,题目里说明当总人数是偶数时,要取出两个人,譬如12个人,那么就要取出6号和7号,如果13个人,只需要取出7号,我一开始就把中位数分两种情况考虑。于是我就这样子被绕了40分钟解决不了,提交代码后更是一直被4/6用例折磨
随着肚子饿了,终于灵光一闪,唉呀妈呀这中位数不就是总人数除以2就可以了嘛,
直接上最终思路如下:
按照题目,有4组成绩 A B C D,人数如下:
A 2
B 4
C 4
D 2
那么最差成绩排名如下:
A 2
B 6
C 10
D 12
注意中位数就是 12 / 2 = 6 这时候就构造一个字段,表示每组成绩的区间
A null 2
B 2 6
C 6 10
D 10 12
只要中位数6 在区间里即可,上表就是B、C都可以。
再来看看万恶的4/6例到底是什么。人数如下:
A 2
D 1
C 2
B 2
那么最差成绩排名如下:
A 2
B 4
C 6
D 7
这个中位数是3.5!!!!不是4,而是3.5!!!再来找区间:
A null 2
B 2 4
C 4 6
D 6 7
很明显,符合中位数3.5的区间只有B!!!如果用中位数是4来算的话,结果是B、C,无法通过审查
代码如下:
#第一步:统计各组成绩最差的名次,以及总人数(为下一步求中位数打基础)
#第二步:非常关键的一步,首先找出中位数(总人数/2即可,保留一位小数!),然后用窗口函数lag找出上一条记录,构造出封闭区间
#第三步:找出中位数所在的区间的grade即可
SELECT grade, SUM(number) over(ORDER BY grade) "t_rank" , SUM(number) over() "cnt" FROM class_grade
#第二步:非常关键的一步,首先找出中位数(总人数/2即可,保留一位小数!),然后用窗口函数lag找出上一条记录,构造出封闭区间
SELECT grade, lag(t_rank,1) over(ORDER BY grade) "before_t_rank", t_rank, ROUND(cnt / 2,1) "mid_num" FROM (SELECT grade, SUM(number) over(ORDER BY grade) "t_rank" , SUM(number) over() "cnt" FROM class_grade) t
#第三步:找出中位数所在的区间的grade即可
SELECT grade FROM (SELECT grade, lag(t_rank,1) over(ORDER BY grade) "before_t_rank", t_rank, ROUND(cnt / 2,1) "mid_num" FROM (SELECT grade, SUM(number) over(ORDER BY grade) "t_rank" , SUM(number) over() "cnt" FROM class_grade) t) tt WHERE mid_num BETWEEN before_t_rank AND t_rank
end~