Re: [问题] 给定n个排好序的整数阵列 找中位数

楼主: FRAXIS (喔喔)   2014-10-14 20:08:49
: ※ 引述《FRAXIS (喔喔)》之铭言:
: : 问题:给定 n 个已排序整数阵列,每个阵列长度为 n
: : 找出 n^2 个元素中的中位数。
: : 在网络上有找到几个讨论
: : http://ppt.cc/PMvU
: : http://ppt.cc/JE1s
: : (这是变形,给定一个n by n矩阵,每行每列都排序,找中位数)
: : 但是我觉得他们的解法到最后都变成O(n^2 lg n)。
: : 而如果忽略掉每个阵列都已经排序的性质,直接在 n^2 个元素中找中位数,
: : 因为找中位数可以在线性时间内完成,
: : 所以在 n^2 个元素内找中位数只需要O(n^2)的时间,也比网页上的解答好。
: : 有没有比O(n^2)快的方法来解决这问题呢?
: 推 springman: 其实就是用 median of median 的算法,只是找到 10/14 09:24
: → springman: median of median m 之后,用 binary search 找出 10/14 09:25
: → springman: 每个排序的阵列中有几个元素比 m 小,看看要找的 10/14 09:25
: → springman: median 比 m 大还是比 m 小。 10/14 09:26
: → springman: 虽然每次可能只能减少 1/4 的元素,不过没关系。 10/14 09:26
: → springman: 每次花的时间,理论值是 O(n) 找 median of median 10/14 09:27
: → springman: O(n log n) 找比 m 小的元素个数。 10/14 09:28
: → springman: 总共应该只需要花 O(log n) 次 10/14 09:28
: → springman: 每次都要使用排序好的阵列。 10/14 09:29
我有想到一个类似的方法,先把每列median找出来,总共有 n 个。
找出这 n 个元素的最大值 max 和最小值 min 及其所在的列max_i, min_i。
然后可以把max_i或是min_i列中删除一半的元素 (这边需要case分析解决base case)
这样每回合至少会有一列的大小变成一半,所以最多有O(n lg n)个回合。
每个回合,找最大值和最小值可以依赖一个balanced binary search tree,
所以时间是O(lg n)。算法的时间复杂度是O(n lg^2 n)。
不过这两个方法,都只使用了每列已排序的性质。
当每行每列都已排序,有没有比O(n lg^2 n)快的简单方法呢?
(理论上是可以O(n) 但是蛮复杂的)
作者: dreamoon (千古悲情人物)   2014-10-14 22:56:00
并无法保证max_i或是min_i列至少有一列可以删掉一半吧?(在不知道min和max实际上是全部的数第几大的情况下)
楼主: FRAXIS (喔喔)   2014-10-14 23:57:00
min小于median且max大于median min_i和max_i删除等量元素
作者: dreamoon (千古悲情人物)   2014-10-15 01:11:00
那你怎么知道min小于median?
楼主: FRAXIS (喔喔)   2014-10-15 01:31:00
因为min小于所有列至少一半的元素
作者: dreamoon (千古悲情人物)   2014-10-15 01:52:00
我好像想懂了,不过你说的少于一半的元素应该还不够轻楚因为虽然一刚开始是求中位数,但过程中会变得不一定是在求中位数
楼主: FRAXIS (喔喔)   2014-10-15 02:27:00
max_i和min_i要删除等量元素 中位数不变
作者: dreamoon (千古悲情人物)   2014-10-15 02:37:00
这不太对吧...?max_i和min_i可能包含不同数目的数?
楼主: FRAXIS (喔喔)   2014-10-15 02:46:00
删除比较小的列的一半元素个数 只要有一个列变成一半就好
作者: dreamoon (千古悲情人物)   2014-10-15 02:50:00
这样的话复杂度还会是O(n lg^2 n)嘛?
楼主: FRAXIS (喔喔)   2014-10-15 02:53:00
每回合至少有一列减半 所以只有O(n lg n)回合
作者: dreamoon (千古悲情人物)   2014-10-15 02:53:00
似乎会耶!
作者: dreamoon (千古悲情人物)   2014-10-15 02:54:00
恩恩,这样的话就比我原本想的容易实做了
楼主: FRAXIS (喔喔)   2014-10-15 02:59:00
实作上的细节还有base case,有可能O(1)的列一切再切..这方法应该也可以找第k大的数字
作者: dreamoon (千古悲情人物)   2014-10-15 03:05:00
我认为只要改程max_i和min_i一律减半,并重新计算下一个round要求的是第几大的数,就可以计算任意第k大了若是求中位数的话,当某列只剩一个数且又被选到应该是可以直接丢掉
作者: esrever   2014-10-16 00:43:00
如果不用 binary search, 而是对那些无法直接和 MoM 比大小的元素 (像是比那排的中位数小,那排中位数却 > MoM)递回算出中位数(并记录每排有几个比它大),这样我们就知该往比 MoM 大的那边还是小的那边递回下去

Links booklink

Contact Us: admin [ a t ] ucptt.com