Median of Two Sorted Arrays-LeetCode

题目

   There are two sorted arrays A and B of size m and n respectively.Find the Median of two sorted arrays.The overall run time complexity should be O(log(m+n)).

题目分析:

   当我第一眼看见这题目时,就想到采用归并排序的方式,在两个数组上设立两个指针从头开始逐一比较。直到找到对应的元素为止。下面是自己开始写的代码:

 1 class Solution {
 2 public:
 3     
 4     double findMedianSortedArrays(int A[], int m, int B[], int n) {
 5          double result,right;
 6          int num=(n+m+1)/2;
 7          int i=0,j=0,cnt=0;
 8          
 9          while(i!=m && j!=n){
10              if(A[i]<=B[j]){
11                  result=A[i];
12                  i++;
13                  cnt++;
14              }
15              
16              else{
17                  result=B[j];                
18                  j++;
19                  cnt++;
20              }
21              
22              if(cnt==num) {
23                 flag=true;
24                 break;
25              }
26          }
27                   
28          while(i!=m){
29              if(cnt==num) break;
30              else{
31                  result=A[i];            
32                  i++;
33                  cnt++;
34              }
35          }
36          
37          while(j!=n){
38              if(cnt==num) break;
39              else{
40                  result=B[j];
41                  j++;
42                  cnt++;
43              }
44          }
45 
46        return result;
47     }

但是运行之后就发现出现了错误,折腾了很久也没有想明白。后面在网上找资料,才明白自己犯了一个最基本的错误,没有理解Median的含义。当Array的个数是奇数时,Median的值是最中间的一个。当它是偶数时,Median的值是n/2和n/2+1上的值的平均数。

网上的解法普遍都是一样的,看了之后发现这种解法确实很巧妙,貌似是某年考研的算法题,先记录下来。

解题思路:

该方法的核心是将原问题转变成一个寻找第k小的数问题(假设两个原序列升序排列),这样中位数实际上是第(m+n)/2小的数(暂不考虑偶数情形).所以只要解决了第k小的数,原问题就得以解决。

 

首先假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,分别代表A和B数组的第k个元素。如果A[k/2-1]<B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k个元素中。也就是说,A[k/2-1]不可能大于两数组合并之后的第k小值,所以我们可以将其抛弃。(注意:这是该算法最核心的地方)。

反证法:

     假设A[k/2-1]大于合并之后的第k小值,我们不妨假定为第(k+1)小值。由于A[k/2-1]小于B[k/2-1],所以B[k/2-1]至少是第(k+2)小值。但实际上,在A中至多存在k/2-1个元素小于A[k/2-1],B中至多存在k/2-1个元素A[k/2-1],所以小于A[k/2-1]的元素个数至多有k/2+k/2-2,小于k,这与A[k/2-1]是k+1的数矛盾。

 

    当A[k/2-1]>B[k/2-1]时也类似。

  当A[k/2-1]==B[k/2-1]时,则我们已经找到第k的元素,也就是这个相等的元素。将其记为m,由于A和B中分别有k/2-1个元素小于m,所以m即是第k小的数。

 

因此总结起来就是:

  •  如果A或者B为空,则直接返回B[k-1]或者A[k-1]。
  •  如果k为1,我们只需要返回A[0]和B[0]中的较小值。
  •  如果A[k/2-1]=B[k/2-1],返回其中一个。

  代码如下:

 1 public:{
 2 
 3     dobule findKth(int A[],int m,int  B[],int n,int k){
 4          //m is equal or smaller than n
 5           if(m<n)
 6               return findKth(B,n,A,m,k);
 7           if(m==0)
 8               return B[k-1];
 9           if(k==1)
10               return min(A[0],B[0]);
11           
12            int pa=min(k/2,m),pb=k-pa;
13            if(A[pa-1]<B[pb-1])
14                 return findKth(A+pa,m-pa,B,n,k-pa);
15            else if(A[pa-1]>B[pb-1])
16                 return findKth(A,m,B+pb,n-pb,k-pb);
17            else
18                 return A[pa-1];
19     }
20 
21     dobule findMedianSortedArrays(int A[],int m,int B[],int n){
22           int k=m+n;
23           if(k & 0x1){
24                 return findKth(A,m,B,n,k/2+1);
25           }
26           else{
27                  return (findKth(A,m,B,n,k/2)+findKth(A,m,B,n,k/2+1))/2;
28           }
29     }
30 };
原文地址:https://www.cnblogs.com/sixue/p/3972690.html