Median of Two Sorted Arrays
LeetCode OJ 4:There are two sorted arrays nums1 and nums2 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)).
思路1:我的做法是依次比较数组A和数组B的最小元素大小,较小者的数组指针右移,直至找到两个数组的中位数。如果m+n为奇数,则中位数为第(m+n)/2+1个元素,否则中位数为第(m+n)/2和第(m+n)/2+1个元素的平均数。在这个过程中,要时刻注意数组长度的问题。
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int i, j, k, m, n, limit; double median, median1, median2; i = j = k = 0; m = nums1.size(); n = nums2.size(); if((m + n) % 2 == 0) limit = (m + n) / 2 - 1 > 0 ? (m + n) / 2 - 1 : 0; else limit = (m + n) / 2; while(k < limit) { if(i == m) j++; else if (j == n) i++; else if(nums1.at(i) < nums2.at(j)) i++; else j++; k++; } if(i == m) median1 = nums2.at(j++); else if(j == n) median1 = nums1.at(i++); else median1 = nums1.at(i) < nums2.at(j) ? nums1.at(i++) : nums2.at(j++); if((m + n) % 2 == 0) { if(i == m) median2 = nums2.at(j++); else if(j == n) median2 = nums1.at(i++); else median2 = nums1.at(i) < nums2.at(j) ? nums1.at(i) : nums2.at(j); median = (median1 + median2) / 2.0; } else median = median1; return median; }
思路2:该方法的核心是将原问题转变成一个寻找第k小数的问题(假设两个原序列升序排列),这样中位数实际上是第(m+n)/2小的数。所以只要解决了第k小数的问题,原问题也得以解决。首先假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,这两个元素分别表示A的第k/2小的元素和B的第k/2小的元素。这两个元素比较共有三种情况:>、<和=。如果A[k/2-1]<B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k小的元素中。换句话说,A[k/2-1]不可能大于两数组合并之后的第k小值,所以我们可以将其抛弃。
此外我们还需要考虑几个边界条件:
- 如果A或者B为空,则直接返回B[k-1]或者A[k-1];
- 如果k为1,我们只需要返回A[0]和B[0]中的较小值;
- 如果A[k/2-1]=B[k/2-1],返回其中一个;
class Solution { public: double findKth(int a[], int m, int b[], int n, int k) { if (m > n) return findKth(b, n, a, m, k); if (m == 0) return b[k - 1]; if (k == 1) return min(a[0], b[0]); int pa = min(k / 2, m), pb = k - pa; if (a[pa - 1] < b[pb - 1]) return findKth(a + pa, m - pa, b, n, k - pa); else if (a[pa - 1] > b[pb - 1]) return findKth(a, m, b + pb, n - pb, k - pb); else return a[pa - 1]; } double findMedianSortedArrays(int A[], int m, int B[], int n) { int total = m + n; if (total & 0x1) return findKth(A, m, B, n, total / 2 + 1); else return (findKth(A, m, B, n, total / 2) + findKth(A, m, B, n, total / 2 + 1)) / 2; } };