Median of Two Sorted Arrays
我们把问题简化,找两排好序数组的第k小的数。
从前向后取,直到取到第k小的数,时间复杂度O(k)
“`c++
class Solution {
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
//merge first
if ((m + n) % 2 == 0)
return double(find((m + n) / 2, A, m, B, n) + find((m + n) / 2 + 1, A, m, B, n)) * 0.5;
else
return double(find((m + n) / 2 + 1, A, m, B, n));
}
int find(int k, int A[], int m, int B[], int n) {
int count = 0, now = INT_MIN;
int i, j;
for (i = 0, j = 0; i < m && j < n;) {
if (A[i] < B[j]) {
++i;
now = A[i-1];
}
else {
++j;
now = B[j-1];
}
++count;
if (count == k) return now;
}
if (i == m)
return B[j + k - count - 1];
else
return A[i + k - count - 1];
}
};
2. 二分法
第一个数组找 k/2 小的数 A[k / 2 - 1],和第二个数组的 k / 2 小的数 B[k / 2 - 1],如果第一个数小,说明答案不可能在第一个数组前 k / 2 个数中;同理,。。。;如果两个数相等,说明这两个数就是我们要找的数。
但是有好多边界条件需要考虑:
- [1], [2,3,4,5,6] 让找第4小的数
- [], [2,3,4] 让找第2小的数
- 递归终止应该是k=1的时候,因为k=1,halfk_b = 0, halfk_a = 1, 无限循环了。
```c++
class Solution {
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
if ((m + n) % 2 == 0) {
int l = find((m + n) / 2, A, m, B, n);
int r = find((m + n) / 2 + 1, A, m, B, n);
return double(l + r) / 2.0;
} else {
return double(find((m + n) / 2 + 1, A, m, B, n));
}
}
int find(int k, int A[], int m, int B[], int n) {
if (k > m + n) return INT_MIN;
if (m < n) return find(k, B, n, A, m); //确保A长
if (n == 0) return A[k-1];
if (k == 1) return min(A[0], B[0]);
int halfk_b = min(k / 2, n); //B短,不能随便取
int halfk_a = k - halfk_b;
if (A[halfk_a - 1] < B[halfk_b - 1]) //a中的前k/2个数是不可能有答案的了
return find(k - halfk_a, A + halfk_a, m - halfk_a, B, n);
else if (A[halfk_a - 1] > B[halfk_b - 1])
return find(k - halfk_b, A, m, B + halfk_b, n - halfk_b);
else
return A[halfk_a - 1];
}
};