求两个排好序的数组的中位数 - 二分法
来源:互联网 发布:盐城网络买花花店 编辑:程序博客网 时间:2024/06/05 17:24
There are two sorted arrays A and B of size m and nrespectively. Find the median of the two sorted arrays.
Example
Given A=[1,2,3,4,5,6]
and B=[2,3,4,5]
, the median is 3.5
.
Given A=[1,2,3]
and B=[4,5]
, the median is 3
.
Challenge
The overall run time complexity should be O(log (m+n))
.
这是Princeton算法公开课的课后习题。 资源:http://www.lintcode.com/en/problem/median-of-two-sorted-arrays/
用二分法很好想,找到a[]和b[]的各自中位数比大小,aUb的中位数肯定在这两个数之间,这样就砍掉了一半,实现二分...
然而实施起来的细节tricky到令我发指(见注释)
主要有两点,
第一,假设a比b短,那么a在1,2对应b奇数,偶数,甚至2个,都是不同的corner case,要各自单独小心处理,把每一个case都弄清楚,毕竟奇数个和偶数个的中位数计算方法是不一样的,并且数组太短的话general method可能会越界。
第二,不是每一次都各砍掉一半的!因为这可能改变aUb的奇偶性,从而导致中位数计算方法改变。安全同时比较有效的做法是,a与b每次都砍掉相同的长度,也就是a的一半。
import java.util.Arrays;import java.lang.Math;class Solution { /** * @param A: An integer array. * @param B: An integer array. * @return: a double whose format is *.5 or *.0 */ public double findMedianSortedArrays(int[] A, int[] B) { int m = A.length; int n = B.length; if (m <= n) return findMedianAB(A, m, B, n); return findMedianAB(B, n, A, m); } private double findMedianAB(int[] A, int m, int[] B, int n) { assert(m <= n); if (m == 0) { return median(B, n); } if (m == 1) { if (n == 1) return MO2(A[0], B[0]); if (n % 2 == 1) { return (MO3(B[n/2 - 1], B[n/2 +1], A[0]) + B[n/2]) / 2.0; } return MO3(B[n/2 - 1], B[n/2], A[0]); } if (m == 2) { if (n == 2) { return MO4(A[0], A[1], B[0], B[1]); } if (n % 2 == 1) { return MO3( B[n/2], Math.max(A[0], B[n/2 - 1]), Math.min(A[1], B[n/2 + 1]) ); } return MO4( B[n/2], B[n/2 - 1], Math.max( A[0], B[n/2 - 2] ), Math.min( A[1], B[n/2 + 1] ) ); } int midA = (m - 1) / 2; int midB = (n - 1) / 2; if (A[midA] <= B[midB]) { // comparing the medians is also ok but a bit slower return findMedianAB( Arrays.copyOfRange(A, midA, m), m - midA, Arrays.copyOfRange(B, 0, n - midA), n - midA ); } // the most tricky part. reduce the length of BOTH A AND B by midA, rather than by half! return findMedianAB( Arrays.copyOfRange(A, 0, m - midA), m - midA, Arrays.copyOfRange(B, midA, n), n - midA ); // try [1,5,6], [2,3,4,7,8] to find that dropping both arrays by half is wrong. // drop-by-midA approach guarantees two things: // 1, at least we are still dropping elements safely (only that we drop a bit less elements from B) // 2, we do not change the being-odd-or-even for the union of sub-A and sub-B from the original one, // which is important because we need to compute the median of the subset in the same way // as we do for the original union of A and B (odd: middle; even: average of 2 middles) } private double MO2(int a, int b) { return (a + b) / 2.0; } private double MO3(int a, int b, int c) { return a + b + c - Math.max(a, Math.max(b, c)) - Math.min(a, Math.min(b, c)); } private double MO4(int a, int b, int c, int d) { int max = Math.max( a, Math.max( b, Math.max( c, d ) ) ); int min = Math.min( a, Math.min( b, Math.min( c, d ) ) ); return (a + b + c + d - max - min) / 2.0; } private double median(int[] arr, int n) { if (n == 0) return Double.NaN; // error if (n % 2 == 0) return (arr[n / 2] + arr[n / 2 - 1]) / 2.0; return arr[n/2]; }}
0 0
- 求两个排好序的数组的中位数 - 二分法
- 求两个数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求这两个数组的中位数
- leetcode 求两个排序数组的中位数
- 求两个有序数组的中位数
- 求两个排序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 两个数组求中位数的问题
- servr
- C语言(6)------基本数据类型之浮点型数据类型
- test
- 【WP】Chrome主题diy
- 在Ubuntu系统中安装Redis数据库服务器(附Redis常用的命令)
- 求两个排好序的数组的中位数 - 二分法
- Android学习1
- Activity四种启动模式
- 在mooc的Python路
- 【WP】Json抓包
- 单个进程最大线程数
- oracle学习笔记名词篇
- 行人检测资源
- UVa 12034 Race