代码改变世界

[LeetCode #4] Median of Two Sorted Arrays

2016-10-01 11:03  amadis  阅读(155)  评论(0编辑  收藏  举报

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)).

 Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0

 Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

 解法一: Merge first, and then find the median; O(m+n)

 1 double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
 2     int totalsize = nums1Size + nums2Size;
 3     int *result = NULL;
 4     int i = 0, j = 0, k = 0;    
 5     double ret;
 6     
 7     if (totalsize == 0){
 8         return -1;
 9     }else{
10         result = (int *)malloc(totalsize * sizeof(int));
11     }
12     
13     if (result == NULL){
14         return -1;
15     }
16     
17     while( (i < nums1Size) && (j < nums2Size) ){
18         if (nums1[i] < nums2[j]){
19             result[k++] = nums1[i++];
20         } else{
21             result[k++] = nums2[j++];
22         }
23     }
24     
25     while (i < nums1Size){
26         result[k++] = nums1[i++];
27     }
28     
29     while (j < nums2Size){
30         result[k++] = nums2[j++];
31     }
32 
33     if ((totalsize % 2) == 1){
34         ret = (double)(result[totalsize/2]);
35     }else{
36         ret = (double)((result[totalsize/2] + result[totalsize/2 - 1])) /2;
37     }    
38     
39     free(result);
40     
41     return ret;
42 }

 

解法二: Binary search; O(log(m+n))

"水中的鱼" (http://fisherlei.blogspot.com/search?q=median) 解释了如何用二分法做, 基本思想是在两个排序了的数组中求第K个数. 不过为何丢弃特定区间没有详细解释. 所以博主在这加以解释.

借用以上文章的图片, 其结论加以修正后附加上分析是 (简单的说,就是或者丢弃最大中位数的右区间,或者丢弃最小中位数的左区间).

1. If (m/2+n/2+1) >= k && a[m/2] >= b[n/2] , drop Section 2 以及 a[m/2];
   推理过程: a[m/2] 大于等于 b[n/2]表明 小与等于a[m/2]的数至少有 a[0] 到a[m/2-1]和b[0]到b[n/2], 一共是(m/2 + n/2 +1)个, 这个数大于等于k. 这表明a[m/2]以及其后的在数组a里的数不可能是第k个数, 所以可以被丢弃.
2. If (m/2+n/2+1) >= k && a[m/2] <= b[n/2] , drop Section 4 以及b[n/2];
   推理过程: 类似 1.
3. If (m/2+n/2+1) < k && a[m/2] <= b[n/2] ,  drop Section 1;
   推理过程: a[m/2] <= b[n/2]表明大于等于a[m/2]的数有 a[m/2+1]到a[m-1]以及b[n/2]到[b[n-1], 一共是(m/2 - 1 + n/2)个. 然后 (m/2-1+n/2) = (m+n) - (m+n)/2 - 1 = (m+n) - (m/2+n/2+1) > (m+n) - k. 所以这意味着a[0]到a[m/2]之间的数不包括第K个数, 因为对第K个数来说, 大与等于它的数有(m+n)-K个. 结论是a[0]到a[m/2]这个区间的数可以被丢弃.
4. If (m/2+n/2+1) < k && a[m/2] >= b[n/2] ,  drop Section 3;
   推理过程: 类似 3
 
 1 int findKth(int a[], int m, int b[], int n, int k)  /* m 以及 n 是数组的长度 */
 2     {  
 3         if (m <= 0) return b[k-1];  
 4         if (n <= 0) return a[k-1];  
 5         if (k <= 1) return (a[0] <= b[0]) ? a[0] : b[0];   
 6     
 7         if ((n/2 + 1 + m/2) >= k)  
 8         {  
 9              if (b[n/2] >= a[m/2]) 
10                   return findKth(a, m, b, n/2, k);  
11              else  
12                   return findKth(a, m/2,b, n, k);  
13         }  
14         else  
15         {  
16              if (b[n/2] >= a[m/2])  
17                   return findKth(a + m/2 + 1, m - (m/2 + 1), b, n, k - (m/2 + 1));  
18                   
19              else  
20                   return findKth( a, m, b + n/2 + 1, n - (n/2 + 1), k - (n/2 + 1));  
21         }  
22     }  
23     
24 double findMedianSortedArrays(int A[], int m, int B[], int n) {  
25     if((n+m)%2 ==0)  
26     {  
27         return (findKth(A,m,B,n, (m+n)/2) + findKth(A,m,B,n, (m+n)/2+1))/2.0;  
28     }  
29     else{
30         return findKth(A,m,B,n, (m+n)/2+1);        
31     }
32 }