leetcode_4_Two Sorted Arrays

题目: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)).

翻译:nums1和nums2是两个已经排好序的数组(升序),求这两个数组合并并排序之后所得数组的中位数。

如,num1 [1,2,3] num2 [2,3,4] 合并 [1,2,2,3,3,4] 中位数为(2+3)/2 = 2.5

如,num1 [1,2,3] num2 [2,3] 合并 [1,2,2,3,3] 中位数为 2

解法1:O(m+n)

该方法是最直观的解法——将两个数组合并为一个新的数组,直接求其中位数。

解法2:O(log (m+n))

该解法的关键是利用如下结论——两个有序数组A,B,若A[K/2-1]<=B[K/2-1],则A[0]~A[K/2-1]一定在合并并排序后的数组的第k个数之前。可用反证法证明。如,A [1,2,3],B[2,3,4] 合并 [1,2,2,3,3,4],令上述结论中的K=4,A[K/2-1]=A[1] =2,B[K/2-1]=B[1]=3,A[1]<B[1],可以看出,此时A的前两个数1,2均在合并后的数组的第四个数之前。

解法3:O(min(m,n))

该解法的关键是利用如下结论——两个有序数组A,B,合并并排序后得到的数组为C,若有一个数X使C[K]=A[X]或者C[K]=B[K-X-1](K为小于A,B元素和的任意值),当且仅当A[X+1]>=B[K-X-1]且B[K-X]>=A[X]。

证明(必要性易证,下面只证明充分性,即如何由“A[X+1]>=B[K-X-1]且B[K-X]>=A[X]”推出“[K]=A[X]或者C[K]=B[K-X-1]):

A[X+1]>=B[K-X-1]可推得B[K-X-1]<=C[K](用反证法可证:若B[K-X-1]>C[K],则必有(X+1)+(K-X-1+1)>(K+1)即K+1>K+1,显然不成立)。

B[K-X]>=A[X]可推得A[X]<=C[K](同样用反证法证明)。

此时得到A[X]<=C[K]且B[K-X-1]<=C[K],又由于A,B均为有序数组,得证C[K]=A[X]或者C[K]=B[K-X-1]

方法3源码如下:

double findkth(int* nums1, int nums1Size, int* nums2, int nums2Size, int kth) {//FinalIndex_nums1,FinalIndex_nums2从0开始;kth based on 0(从0开始,不知道英文是不是这么讲。。)     #define ifn  (int)0x7fffffff #define nifn (int)0x80000000 #define A(i) (i>nums1Size-1?ifn:(i<0?nifn:nums1[i])) #define B(i) (i>nums2Size-1?ifn:(i<0?nifn:nums2[i]))     if (nums1Size > nums2Size)         return findkth(nums2, nums2Size, nums1, nums1Size, kth);     if (nums1Size == 0)         return nums2[kth];

    //nums1 is shorter than nums2 below     int x = 0, l = 0, r = 0;

    if (kth > (nums1Size – 1))         r = nums1Size – 1;     else         r = kth;     bool Nums1beforeKth = false;     while (l <= r)     {         x = (l + r) >> 1;//即x = (l + r)/2;         double t1 = A(x + 1);         double t2 = B(kth – x – 1);         if (A(x+1) < B(kth – x – 1))             l = x + 1;         else if (B(kth – x) < A(x))             r = x – 1;         else         {             Nums1beforeKth = true;             if (nums1[x]>nums2[kth – x – 1])             {                 return nums1[x];             }             else             {                 return nums2[kth – x – 1];             }         }         }     if (!Nums1beforeKth)     {         return nums2[kth];     }     }

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {//log(min(m,n))         bool odd = false;     if ((nums1Size + nums2Size) % 2 == 1)         odd = true;     if (odd)     {         return findkth(nums1, nums1Size, nums2, nums2Size, (nums1Size + nums2Size) / 2);     }     else     {         double mid_1 = findkth(nums1, nums1Size, nums2, nums2Size, (nums1Size + nums2Size) / 2);         double mid_2 = findkth(nums1, nums1Size, nums2, nums2Size, ((nums1Size + nums2Size) / 2) – 1);         return (mid_1 + mid_2) / 2;     } }

点赞