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




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值