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 };

 

你可能感兴趣的:(LeetCode)