Median of Two Sorted Arrays
There are two sorted arrays A and B of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
SOLTION 1:
1. 我们借用findKthNumber的思想。先实现findKthNumber,如果是偶数个,则把中间2个加起来平均,奇数就用中间的。
2. 为了达到LOG级的复杂度,我们可以这样:
每次在A,B取前k/2个元素。有以下这些情况:
1). A的元素个数 < k/2. 则我们可以丢弃B前k/2. 反之亦然
证明:
我们使用反证法。
假设第K大在B的前k/2中,例如位置在索引m(m <= k/2-1)那么A必然拥有前k中的k -(m+1)个元素,而
m <= k/2-1,则 m+1 <= k/2 , k - (m+1) >= k/2与条件:A的元素不够k/2矛盾,所以假设不成立,得证。
举个栗子:
A: 6 7 8
B: 1 2 3 4 5
找第8大的数字,
2). A[mid] < B[mid] (mid是k/2 -1索引处的元素)。
这种情况下,我们可以丢弃A前k/2。
证明:
我们使用反证法。
假设第K大在A的前k/2中记为maxK,例如位置在索引m(m <= k/2-1)那么B必然拥有前k中的k -(m+1)个元素,而
m <= k/2-1,则 m+1 <= k/2 , k - (m+1) > k/2
推出B[mid] <= maxK
而A[mid] >= maxK 推出 A[mid]>=B[mid], 与题设矛盾。所以假设不能成立。
举个栗子:
A: 1 2
B: 4 5 6 7 8
找第四大的数字 我们就可以首先排除1,2.
1 public double findMedianSortedArrays(int A[], int B[]) { 2 if (A == null || B == null) { 3 return 0; 4 } 5 6 int len = A.length + B.length; 7 8 double ret = 0; 9 // 偶数个元素 10 if (len % 2 == 0) { 11 ret = (findKth(A, B, 0, 0, len / 2) + findKth(A, B, 0, 0, len / 2 + 1)) / (double)2.0; 12 } else { 13 // 奇数个元素 14 ret = findKth(A, B, 0, 0, len / 2 + 1); 15 } 16 17 return ret; 18 } 19 20 // Find the Kth large number. 21 public int findKth(int A[], int B[], int indexA, int indexB, int k) { 22 int lenA = A.length; 23 int lenB = B.length; 24 25 if (indexA >= lenA) { 26 return B[indexB + k - 1]; 27 } else if (indexB >= lenB) { 28 return A[indexA + k - 1]; 29 } 30 31 // Base Case, pay attention. 在这里必须要退出。因为k = 1的时候,不可能再分了。 32 if (k == 1) { 33 return Math.min(A[indexA], B[indexB]); 34 } 35 36 // -1是因为索引本身是从0开始的。而前k大元素含有k个元素。 37 int mid = k / 2 - 1; 38 39 // 注意,越界条件是 >= lenA. 怎么老是犯这个错误。。 40 int keyA = indexA + mid >= lenA ? Integer.MAX_VALUE: A[indexA + mid]; 41 int keyB = indexB + mid >= lenB ? Integer.MAX_VALUE: B[indexB + mid]; 42 43 // 因为丢弃了k / 2个元素 44 int kNew = k - k / 2; 45 46 if (keyA < keyB) { 47 return findKth(A, B, indexA + k / 2, indexB, kNew); 48 } else { 49 return findKth(A, B, indexA, indexB + k / 2, kNew); 50 } 51 }
2015.1.25
可以优化一下,在找到kth number时可以及时退出:
1 public class Solution { 2 public double findMedianSortedArrays(int A[], int B[]) { 3 //2257 4 if (A == null || B == null) { 5 return 0; 6 } 7 8 int len = A.length + B.length; 9 if (len % 2 == 0) { 10 return (double)(dfs(A, B, 0, 0, len / 2) + dfs(A, B, 0, 0, len / 2 + 1)) / 2.0; 11 } else { 12 return dfs(A, B, 0, 0, len / 2 + 1); 13 } 14 } 15 16 public double dfs1(int A[], int B[], int aStart, int bStart, int k) { 17 if (aStart >= A.length) { 18 return B[bStart + k - 1]; 19 } else if (bStart >= B.length) { 20 return A[aStart + k - 1]; 21 } 22 23 if (k == 1) { 24 return Math.min(A[aStart], B[bStart]); 25 } 26 27 // k = 4; 28 // mid = 1; 29 int mid = k / 2 - 1; 30 31 if (aStart + mid >= A.length) { 32 // drop the left side of B. 33 return dfs(A, B, aStart, bStart + k / 2, k - k / 2); 34 } else if (bStart + mid >= B.length) { 35 // drop the left side of A. 36 return dfs(A, B, aStart + k / 2, bStart, k - k / 2); 37 } else if (A[aStart + mid] > B[bStart + mid]) { 38 // drop the left side of B. 39 return dfs(A, B, aStart, bStart + k / 2, k - k / 2); 40 // 当2者相等,有2种情况: 41 // 1. 当k为偶数,则kth存在于任何一个结尾处,其实也是可以丢弃一半的。 42 // 2. 当k为奇数,则kth不存在于A,B的left side。也是可以丢弃任意一半。 43 //} else if (A[aStart + mid] < B[bStart + mid]) { 44 } else { 45 return dfs(A, B, aStart + k / 2, bStart, k - k / 2); 46 } 47 48 //return A[aStart + mid]; 49 } 50 51 public double dfs(int A[], int B[], int aStart, int bStart, int k) { 52 if (aStart >= A.length) { 53 return B[bStart + k - 1]; 54 } else if (bStart >= B.length) { 55 return A[aStart + k - 1]; 56 } 57 58 if (k == 1) { 59 return Math.min(A[aStart], B[bStart]); 60 } 61 62 // k = 4; 63 // mid = 1; 64 int mid = k / 2 - 1; 65 66 if (aStart + mid >= A.length) { 67 // drop the left side of B. 68 return dfs(A, B, aStart, bStart + k / 2, k - k / 2); 69 } else if (bStart + mid >= B.length) { 70 // drop the left side of A. 71 return dfs(A, B, aStart + k / 2, bStart, k - k / 2); 72 } else if (A[aStart + mid] > B[bStart + mid]) { 73 // drop the left side of B. 74 return dfs(A, B, aStart, bStart + k / 2, k - k / 2); 75 } else if (A[aStart + mid] < B[bStart + mid]) { 76 return dfs(A, B, aStart + k / 2, bStart, k - k / 2); 77 } else { 78 // drop the left side of A. 79 //return dfs(A, B, aStart + k / 2, bStart, k - k / 2); 80 if (k % 2 == 0){ 81 return A[aStart + mid]; 82 } 83 84 // can drop both sides. 85 return dfs(A, B, aStart + k / 2, bStart + k / 2, 1); 86 } 87 88 //return A[aStart + mid]; 89 } 90 }
GITHUB:
https://github.com/yuzhangcmu/LeetCode_algorithm/blob/master/array/FindMedianSortedArrays.java