4. Median of Two Sorted Arrays 【Hard】 分治法

看了题解才会做。题解是把取中位数的问题转化为了取第k小的数的问题。

题解的思路是:先判断两数组长度和m+n是奇数还是偶数。奇数则直接取两数组的第(m+n) / 2 + 1小的数,偶数则取第(m+n) / 2和第(m+n) / 2 + 1小的数取平均值。

取第k小的数的办法是:给定两数组a(长度为m)和b(长度为n)和k。

                                         若m>n则调换两个数组;若m=0,则意味着a数组空,第k小在b里,直接返回b[k - 1];若k=1,则第k小必然在a[0]和b[0]中,返回a[0]和b[0]中的最小值。

                                         若上述条件都不符合,则m>=1且k>=2,a不为空且不确定第k小的数在a还是在b。那么就要想办法把a和b的前面的一些元素去掉。

                                         设去掉a的前x个数,那就要使x尽可能靠近k / 2且不能超过m,所以x=min(k / 2, m)。然后设去掉b的前y个数,y=k - x。

                                         比较a[x - 1]和b[y - 1]。若前者更大,则b的前y个数都不可能是第k小的数,下一个递归去比较a(长度m)和b+y(长度为n - y);若后者更大,则a的前x个数都不可能是第k小的数,一个递归去比较a + x(长度m - x)和b(长度为n);若相等,则a[x - 1]和b[y - 1]都是第k小的数,随便return一个。


看答案前想了很多办法,花了2个小时都没做出来,想想还是放弃了。感觉很难。


double findKth(int a[], int m, int b[], int n, int k) {  
    //always assume that m is equal or smaller than n  
    if (m > n)  
        return findKth(b, n, a, m, k);  
    if (m == 0)  
        return b[k - 1];  
    if (k == 1)  
        return min(a[0], b[0]);  
        
    //divide k into two parts  
    int x = min(k / 2, m), y = k - x;  
    if (a[x - 1] < b[y - 1])  
        return findKth(a + x, m - x, b, n, k - x);  
    else if (a[x - 1] > b[y - 1])  
        return findKth(a, m, b + y, n - y, k - y);  
    else  
        return a[x - 1];  
}  

class Solution  
{
public:  
    double find(int A[], int m, int B[], int n)  
    {  
        int total = m + n;  
        if (total & 0x1)
            return findKth(A, m, B, n, total / 2 + 1);  
        else  
            return (findKth(A, m, B, n, total / 2) +
					findKth(A, m, B, n, total / 2 + 1)) / 2;  
    }  
    double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
    	int l1 = nums1.size(), l2 = nums2.size();
    	int *a = new int[l1], *b = new int[l2];
    	for (int i = 0; i < l1; ++i) a[i] = nums1[i];
    	for (int i = 0; i < l2; ++i) b[i] = nums2[i];
    	return find(a, l1, b, l2);
	}
};  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值