Leetcode:Median of Two Sorted Arrays

Question

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

Solution

方案一:将两个数组合成一个数组,使用快速排序算法进行排序,然后找到中位数。
  空间复杂度:

O(m+n)

  时间复杂度:
  
O(log(m+n))

方案二:对nums1和nums2数组分别使用二分查找法,直到最后两个数组剩下一个或两个元素,这样就很容易找到中位数。
  空间复杂度:
  
O(1)

  时间复杂度:
  
O(log(max(m,n))

方案一代码:
  这里我没有自己编写快速排序算法,使用的是python的内建函数。最后的平均速度是124ms。

class Solution:
    # @param {integer[]} nums1
    # @param {integer[]} nums2
    # @return {float}
    def findMedianSortedArrays(self, nums1, nums2):
        alln = nums1 + nums2
        alln.sort()
        maxn = len(alln)
        if maxn % 2 == 1:
            return alln[maxn/2]
        else:
            return ( alln[maxn/2] + alln[maxn/2 - 1] ) / 2.0

方案二代码:
这里的代码总是又几个数据不能运行,所以这个暂时先放一放,代码我就暂时不贴上来了。

其他人的解决方案

C语言

double 
findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) 
{
    int left = (nums1Size + nums2Size + 1) / 2, right = left;
    if((nums1Size + nums2Size) % 2 == 0)
        right++;
    //printf("left:%d\tright:%d\n", left, right);
    //find the left smallest element, comparing from the start of array--O(left)
    //BETTER: left/2, left/4, left/8...
    int i = 0, j = 0, t = left, k = (t + 1) / 2;
    while(k > 0)
    {
        if(i + k > nums1Size || j + k > nums2Size)
            break;
        if(nums1[i+k-1] < nums2[j+k-1]) 
            i += k;
        else
            j += k;
        t -= k;
        k = (t + 1) / 2;
    }
    while(t > 0 && i < nums1Size && j < nums2Size)
    {
        if(nums1[i] < nums2[j])
            i++;
        else
            j++;
        t--;
    }
    if(t > 0)
    {
        if(i == nums1Size)
            j += t;
        else if(j == nums2Size)
            i += t;
    }
    int mid_left, mid_right;
    if(i > 0 && j > 0)
        mid_left = (nums1[i-1] < nums2[j-1])?nums2[j-1]:nums1[i-1];
    else if(i == 0)
        mid_left = nums2[j-1];
    else if(j == 0)
        mid_left = nums1[i-1];
    if(right > left)
    {
        if(i < nums1Size && j < nums2Size)
            mid_right = (nums1[i] < nums2[j])?nums1[i]:nums2[j];
        else if(i == nums1Size)
            mid_right = nums2[j];
        else if(j == nums2Size)
            mid_right = nums1[i];
    }
    else
        mid_right = mid_left;
    //printf("mid_left:%d\tmid_right:%d\n", mid_left, mid_right);
    return (mid_left + mid_right) / 2.0;
}

C++代码

public:   
double findMedianSortedArrays(vector<int>& nums1,vector<int>& nums2)
{
    int m,n,k;
    m = nums1.size();
    n = nums2.size();
    auto beg1 = nums1.begin(),beg2 = nums2.begin();
    k = (m+n)>>1;
    if((m+n) & 0x1)
        return find_kth(nums1,beg1,nums2,beg2,k+1);
    else 
        return (find_kth(nums1,beg1,nums2,beg2,k) + find_kth(nums1,beg1,nums2,beg2,k+1))/2.0;

}
private:
double find_kth(vector<int>& nums1,vector<int>::iterator beg1,vector<int>& nums2,vector<int>::iterator beg2,int k)
{
    int m = nums1.end() - beg1,n = nums2.end() - beg2;
    if(m>n) 
        return find_kth(nums2,beg2,nums1,beg1,k);
    if(m==0) return *(beg2+k-1);
    if(k==1) return min(*beg1,*beg2);
    int m1 = min(k/2,m),m2 = k-m1;
    if(*(beg1+m1-1)<*(beg2+m2-1))
        return find_kth(nums1,beg1+m1,nums2,beg2,k-m1);
    else if(*(beg1+m1-1)>*(beg2+m2-1))
        return find_kth(nums1,beg1,nums2,beg2+m2,k-m2);
    else
        return *(beg1+m1-1);
}

Java代码

int l1 = -1;
int l2 = -1;
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    int tar = (nums1.length + nums2.length);
    if (nums1.length * nums2.length == 0) {
        if (nums1.length == 0) {
            if (tar % 2 == 0)
                return (nums2[nums2.length / 2 - 1] + nums2[nums2.length / 2]) / 2.0;
            return nums2[nums2.length / 2];
        } else {
            if (tar % 2 == 0)
                return (nums1[nums1.length / 2 - 1] + nums1[nums1.length / 2]) / 2.0;
            return nums1[nums1.length / 2];

        }

    }

    if (tar % 2 == 0) {
        return (find(tar / 2 - 1, nums1, nums2) + find(0, nums1, nums2)) / 2.0;

    } else {
        return find(tar / 2, nums1, nums2);

    }

}

public int find(int next, int[] nums1, int[] nums2) {

    if (next == 0) {
        if (l1 == nums1.length - 1) {
            return nums2[l2++ + 1];
        } else if (l2 == nums2.length - 1) {
            return nums1[l1++ + 1];

        }
        return nums1[l1 + 1] > nums2[l2 + 1] ? nums2[l2++ + 1]
                : nums1[l1++ + 1];

    }
    if (next == 1) {
        if (nums1[l1 + 1] > nums2[l2 + 1]) {
            l2++;
        } else {
            l1++;
        }
        return find(0, nums1, nums2);
    } else {
        int t1 = (next - 2) / 2 % (nums1.length - 1 - l1) + 1;
        int t2 = (next - 2) / 2 % (nums2.length - l2 - 1) + 1;
        if (nums1[l1 + t1] >= nums2[t2 + l2]) {
            if (t2 + l2 == nums2.length - 1) {
                next = next - t2;
                l2 = t2 + l2;
                l1 = l1 + next;
                return nums1[l1++ + 1];
            } else {
                next = next - t2;
                l2 = t2 + l2;
                return find(next, nums1, nums2);

            }

        } else {
            if (t1 + l1 == nums1.length - 1) {
                next = next - t1;
                l1 = t1 + l1;
                l2 = l2 + next;
                return nums2[l2++ + 1];

            } else {
                next = next - t1;
                l1 = t1 + l1;
                return find(next, nums1, nums2);

            }

        }

    }

}

Summarizes

这一道题我花了很长时间,知道对两个数组使用折半搜索,但是最后的地方总是想不明白。内建函数是经过优化的,所以速度会比自己写的函数要快很多,以后如果能使用内建函数的地方,最好还是使用内建函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值