弱鸡进城纪实。
昨晚睡前开搞的一道 LeetCode,#4 Median of Two Sorted Arrays,大意是,给定两个有序数组,找出这两个数组的中位数,时间复杂度在 O (logN) 内。
OK,拿到这道题的第一思路是并归排序之后取中值。但是因为复杂度为 O (M+N),并不符合题意,于是另作他想。
昨晚因为太晚没有细想,就是模模糊糊觉得对数时间复杂度这个应该和二分搜索有关,具体的又没什么头绪。
今天继续攻略这道题,未果,死马当活马医的写了一个并归算法提交上去没想到居然 AC,囧 rz……
但是怎么想怎么不爽,这明显他喵的不对也能过?得过且过明显不是我的忍道,于是上网找了些资料,才知道这道题应该做如是处理:
求两个有序数组的中位数,其实可以作为 “求两个有序数组的第 K 个最小值” 的特殊情况来看待。
而我们可以轻易得到这样三个结论:
有序数组 A 的第 K/2 个值如果比有序数组 B 的第 K/2 个值小,那么有序数组 A 的前 K/2 个值中不可能会有有序数组 A+B 的第 K 个值。
* 有序数组 B 的第 K/2 个值如果比有序数组 A 的第 K/2 个值小,那么有序数组 B 的前 K/2 个值中不可能会有有序数组 A+B 的第 K 个值。**
有序数组 A 的第 K/2 个值如果与有序数组 B 的第 K/2 个值相等,那么该值即为 A+B 的第 K 个值
进一步的,我们可以得出一个这样的结论:如果 A 数组中第 Ka 个数比 B 数组中得第 K-Ka 个数小,那么 A+B 的第 K 个数肯定不在 A 数组的前 Ka 个数中。
由此我们可以写出一个递归的函数,其作用为返回有序数列 A 和 B 组合之后的第 K 个数:
1 | double findKth(int A[], int m, int B[], int n, int k){ |
OK,到这里基本就结束了,不过这道题在处理两个数列个数之和为偶数的时候是取中间两个中位数的均值作为最终的中位数的,所以这里在外边需要对于奇偶性进行分开讨论:
1 | double findMedianSortedArrays(int A[], int m, int B[], int n) { |
OK,到这里这道题就结束了,整个复杂度是 O (log (M+N)),最后运行的结果也很漂亮,108ms,基本是最靠前的了。
这里必须吐槽一句,同样的写法,我用 Java 提交,用时将近一秒,用 CPP 提交,用时 108ms,不得不感叹一下,Java 真的很不适合做这种数组类型的题……
(不,主要是我 LOW)
v1.5.2