[LeetCode]Median of Two Sorted Arrays

思路:

首先最容易的想到的是新开一个数组C[n+m],将数组A和B的值赋到C中,快排,找中数,时间复杂度为O((n+m)log(n+m))和空间复杂度为O(n+m)。这种方法完全没有利用到A、B是有序数组的条件,因此复杂度较高。


第二种方法是利用A、B是有序数组,用两个指示变量 i ,j 分别指向A和B的第一个元素,通过比较A[i]与B[j]:A[i]<B[j],i++;否则 j++,知道找到第(n+m)/2点。时间复杂度为O(n+m)。

以上两种方法均达不到题目对复杂度为O(log(n+m))的要求,还需要进一步优化。


我们先将问题转化为更一般的问题:寻找第k小的数。首先假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,这两个元素分别表示A的第k/2小的元素和B的k/2小的元素。这两个元素比较共有三种情况:>、<和=。

1、A[k/2-1] < B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k小的元素中。换句话说,A[k/2-1]不可能大于两数组合并之后的第k小值,所以我们可以将其抛弃。

2、A[k/2-1] < B[k/2-1],与情况1类似。

3、A[k/2-1] = B[k/2-1],则A[k/2-1]或B[k/2-1]即为第k小的数。

注:仔细想想,其实方法三是由方法二衍生而来的,第二种方法是每次抛弃一个元素(i++ or j++),而方法三是一次抛弃k/2个数据,提高了效率。

代码:

方法二:

class Solution {
public:
    double findMedianSortedArrays(int A[], int m, int B[], int n) {
        int len=n+m;
        int target=(n+m)/2;
        int i=0,j=0;
        int a[m+n+5],ans=0;
        while(ans<=target)
        {
        	if(j==n)
        	{
	        	a[ans++]=A[i];
	        	i++;
	        	continue;
	        }
	        if(i==m)
	        {
        		a[ans++]=B[j];
        		j++;
        		continue;
        	}
        	if(A[i]>B[j])
        	{
				a[ans++]=B[j];	        		
				j++;	        	
	        }
	        if(A[i]<=B[j])
	        {
	        	a[ans++]=A[i];
        		i++;
        	}	        
        }
        double median; 
        if(len&1)
        median=(double)a[target];
        else
        median=(double)(a[target]+a[target-1])/2;
        return median;
    }
};
方法三 :

class Solution {
public:
    double findk(int A[], int m, int B[], int n, int k)
    {
        if(m>n)
        return findk(B,n,A,m,k);
        if(m==0)
        return B[k-1];
        if(k==1)
        return min(A[0],B[0]);
        int k1=min(m,k/2);
        int k2=k-k1;
        if(A[k1-1]<B[k2-1])
        return findk(A+k1,m-k1,B,n,k-k1);
        else if(A[k1-1]>B[k2-1])
        return findk(A,m,B+k2,n-k2,k-k2);
        return A[k1-1];
    }
    double findMedianSortedArrays(int A[], int m, int B[], int n) {
        int k=m+n;
        if(k&1)
        return findk(A,m,B,n,k/2+1);
        return (findk(A,m,B,n,k/2)+findk(A,m,B,n,k/2+1))/2;
    }
};



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值