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)).
1 public static double MedianofTwoSortedArrays(int[] A, int[] B) 2 { 3 int m = A.Length; 4 int n = B.Length; 5 6 if (m + n <= 1) 7 { 8 if (m == 0) 9 return B[0]; 10 else if (n == 0) 11 return A[0]; 12 } 13 int mid1 = 0, mid2 = 0; 14 15 //if m + n % 2 == 0, mid2 = mid + 1; else mid1 = mid2 = (m + n) / 2 + 1; 16 mid1 = (m + n) / 2 + (m + n) % 2; 17 mid2 = (m + n) / 2 + 1; 18 19 int pa = 0, pb = 0, count = 0; 20 double median1 = 0, median2 = 0; 21 22 //merge two array and keep counting. set median1 and median2 when count = mid1 or mid2 respectively. 23 while (count < mid2) 24 { 25 if ((pa < m && A[pa] <= B[pb]) || pa >= n) 26 { 27 count++; 28 if (count == mid1) 29 median1 = A[pa]; 30 if (count == mid2) 31 median2 = A[pa]; 32 pa++; 33 } 34 else 35 { 36 count++; 37 if (count == mid1) 38 median1 = B[pb]; 39 if (count == mid2) 40 median2 = B[pb]; 41 pb++; 42 } 43 } 44 45 return (median1 + median2) / 2; 46 }
代码分析:
O(m + n)的做法,把mid1 和 mid2 算出来,如果总长 m + n 是odd, mid1 = mid2, 如果是even, mid2 = mid1 + 1.
然后pa, pb 指针, merge两个数组同时count, 得到median1和median2后求出median。
奇怪的是leetcode要求时间复杂度O(log(m+n)),这个O(m+n)的做法居然过了large case.
1 public static double MedianofTwoSortedArraysOpt(int[] A, int[] B) 2 { 3 int t = A.Length + B.Length; 4 if (t % 2 == 0) 5 { 6 return ((double)FindKth(A, 0, A.Length, B, 0, B.Length, t / 2) + 7 (double)FindKth(A, 0, A.Length, B, 0, B.Length, t / 2 + 1)) / 2; 8 } 9 10 return FindKth(A, 0, A.Length, B, 0, B.Length, t / 2 + 1); 11 } 12 13 public static int FindKth(int[] A, int aoffset, int m, int[] B, int boffset, int n, int k) 14 { 15 //Keep the A is the shorter array. 16 if (m > n) FindKth(B, boffset, n, A, aoffset, m, k); 17 18 if (m == 0) return B[k - 1]; 19 if (k == 1) return Math.Min(A[aoffset], B[boffset]); 20 21 //set pa and pb pointer 22 int pa = Math.Min(k / 2, m); 23 int pb = k - pa; 24 25 if (A[aoffset + pa - 1] < B[boffset + pb - 1]) return FindKth(A, aoffset + pa, m - pa, B, boffset, n, k - pa); 26 27 return FindKth(A, aoffset, m, B, boffset + pb, n - pb, k - pb); 28 }
代码分析:
这个应该是O(log(k))的做法。因为找两个sorted array 的中位数,其实就是找第K个数的变体,如果m + n 是odd, 那就是找第 (m + n) / 2 个数,如果是even, 那就是找 (m + n) / 2, (m + n) / 2 + 1的平均值。
这个FindKth()函数也是在mitbbs上看到的,非常牛。用C++写就更简洁了。
还是想记下这个FindKth()的思路。
1. 保持A是短的那一个数组,B是长的
2. 平分k, 一半在A,一半在B (如果A的长度不足K/2,那就pa就指到最后一个)
3. 如果pa的值 < pb的值,那证明第K个数肯定不会出现在pa之前,递归,把A数组pa之前的砍掉,同理递归砍B数组。(代码中pa - 1是A的index是为了方便,因为题目第K个数,K是从1开始算的)。
4. 递归到 m == 0 (短的数组用完了) 就返回 B[k - 1], 或者k == 1(找第一个数)就返回min(A第一个数,B第一个数)。(代码中用A[aoffset],因为C#不支持指针,C++里A[0]的完了)。