要求:Median of Two Sorted Arrays (求两个排序数组的中位数)
分析:1. 两个数组含有的数字总数为偶数或奇数两种情况。2. 有数组可能为空。
解决方法:
1.排序法
时间复杂度O(m+n),空间复杂度 O(m+n)
归并排序到一个新的数组,求出中位数。
代码:
class Solution { public: double findMedianSortedArrays(int A[], int m, int B[], int n) { int *C = new int[m+n]; int id1, id2, id3; id1 = id2 = id3 = 0; while(id1 < m && id2 < n) { while(id1 < m && id2 < n && A[id1] <= B[id2]) C[id3++] = A[id1++]; while(id1 < m && id2 < n && B[id2] <= A[id1]) C[id3++] = B[id2++]; } while(id1 < m) C[id3++] = A[id1++]; while(id2 < n) C[id3++] = B[id2++]; if(id3 & 0x1) { id1 = C[id3>>1]; delete[] C; return (double)id1; } else { id1 = C[id3>>1]; id2 = C[(id3>>1)-1]; delete[] C; return ((double)id1 + (double)id2) / 2.0; } } };
2.使用两个指针查找
时间复杂度O((m+n)/2),空间复杂度O(1)
数组 A ,B 分别使用一个指针,都从头或者从尾部开始走 (m+n) /2(m+n & 0x ==1 时) 步,找出中位数。
代码如下:
1 class Solution { 2 public: 3 double findMedianSortedArrays(int A[], int m, int B[], int n) { 4 if(m == 0) return findMediaArray(B, n); 5 if(n == 0) return findMediaArray(A, m); 6 unsigned id1, id2; 7 id1 = id2 = 0; 8 if((m + n) & 0x1) 9 { 10 unsigned med = 0; 11 while(id1 < m && id2 < n) 12 { 13 while(id1 < m && id2 < n && A[id1] <= B[id2]) 14 { 15 ++id1; 16 ++med; 17 if(med == (m + n + 1) >> 1) return (double)A[id1 - 1]; 18 } 19 while(id1 < m && id2 < n && B[id2] <= A[id1]) 20 { 21 ++id2; 22 ++med; 23 if(med == (m + n + 1) >> 1) return (double)B[id2 - 1]; 24 } 25 } 26 while(id2 < n) 27 { 28 ++med; 29 if(med == (m + n + 1) >> 1) return (double)B[id2]; 30 ++id2; 31 } 32 while(id1 < m) 33 { 34 ++med; 35 if(med == (m + n + 1) >> 1) return (double)A[id1]; 36 ++id1; 37 } 38 } 39 else 40 { 41 unsigned cnt = 0; 42 int med1 = 0, med2 = 0; 43 while(id1 < m && id2 < n) 44 { 45 while(id1 < m && id2 < n && A[id1] <= B[id2]) 46 { 47 ++id1; 48 ++cnt; 49 if(cnt == (m + n) >> 1) med1 = A[id1 - 1]; 50 if(cnt == ((m + n) >> 1) + 1) 51 { 52 med2 = A[id1 - 1]; 53 return ((double)med1 +(double)med2) / 2; 54 } 55 } 56 while(id1 < m && id2 < n && B[id2] <= A[id1]) 57 { 58 ++id2; 59 ++cnt; 60 if(cnt == ((m + n) >> 1)) med1 = B[id2 - 1]; 61 if(cnt == ((m + n) >> 1) + 1) 62 { 63 med2 = B[id2 - 1]; 64 return ((double)med1 +(double)med2) / 2; 65 } 66 } 67 } 68 while(id2 < n) 69 { 70 ++cnt; 71 if(cnt == (m + n) >> 1) med1 = B[id2]; 72 if(cnt == ((m + n) >> 1) + 1) 73 { 74 med2 = B[id2]; 75 return ((double)med1 +(double)med2) / 2; 76 } 77 ++id2; 78 } 79 while(id1 < m) 80 { 81 ++cnt; 82 if(cnt == (m + n) >> 1) med1 = A[id1]; 83 if(cnt == ((m + n) >> 1) + 1) 84 { 85 med2 = A[id1]; 86 return ((double)med1 +(double)med2) / 2; 87 } 88 ++id1; 89 } 90 } 91 } 92 double findMediaArray(int A[], int m){ 93 if(m == 0) return 0.0; 94 if(m & 0x1) return (double)A[(m - 1) >> 1]; 95 else return ((double)A[m >> 1] + (double)A[(m >> 1) - 1]) / 2; 96 } 97 98 };
3.类二分查找
时间复杂度O(lg((m+n)/2)) ~ O(lg(m+n)),空间复杂度O(1)
将问题化解为:查找两个数组中从小到大第 K 个元素。(从大到小亦可)以下为求解过程:
步骤:假定数组 A 中元素个数 m 小于数组 B 中元素个数 n 。从数组A中取出第 min(K/2,m)=pa 个元素,从数组B中取出第 K-pa = pb 个元素,若:
a. A[pa] < B[pb],则将问题化为取数组 A+pa,与数组 B 中第 K - pb 个元素。
b. A[pa] = B[pb], 则第 k 个元素就是 A[pa] 或者 B[pb]。
c. A[pa] > B[pb],则将问题化为取数组 A,与数组 B+pb 中第 K - pa 个元素。
代码:
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]; } } class Solution { public: double findMedianSortedArrays(int A[], int m, int B[], int n) { int total = m + n; if(total == 0) return 0.0; if(total & 0x1){ return findKth(A, m, B, n, (total + 1) >> 1); }else{ return (findKth(A, m, B, n, total >> 1) + findKth(A, m, B, n, (total >> 1) + 1)) / 2.0; } } };