Median of Two Sorted Arrays

这题对我来说挺难,先用O(n)的笨办法过了,leetcode的输入集只有想不到没有做不到,所以不断加上各种边界条件代码简直就不能看了……

先附上O(n)的解法,即把两个有序数组扫一遍,归并成新的有序数组,然后取Median。

Java 版:

public class Solution {
    public double findMedianSortedArrays(int A[], int B[]) {
        int len = A.length + B.length;
        int[] tem = new int[len];
        int i = 0;
        int j = 0;
        int t = 0;
        while(j<B.length && i<A.length){
            if(A[i]>=B[j]){
                tem[t] = B[j];
                j++;
                t++;
            }else{
                tem[t] = A[i];
                i++;
                t++;		            
            }
        }
        if(i<A.length){
        	for(t=t;t<len;t++,i++){
        		tem[t] = A[i];
        	}
        }
        if(j<B.length){
        	for(t=t;t<len;t++,j++){
        		tem[t] = B[j];
        	}
        }
        if(len%2==1)
        	return tem[len/2];
        else{
        	return (double)(tem[len/2]+tem[len/2-1])/2;
        }
    }
}

之后发现,在算法导论9.3-8有这道题,而且还尼玛是作业题……瞬间学渣都是泪……当然leetcode上不要求两数组等长,而且总长度奇偶不同,答案也会因为取中位数还是取居中两者平均值而变化,情况更复杂。

在网上找到此题的解法,千篇一律来自 leetcode之median of two sorted arrays 以及 leetcode 4 median of two sorted arrays 这两篇所讲述的算法。算法简洁巧妙,讲问题转化为求第K小(当两数组长和为奇数)或者第K小和第K+1小的平均数(当两数组长和为偶数)。源程序为C++,现将其改写为Java版。但是在Leetcode的输入集下,这种解法的耗时明显比上一种“笨办法”还要慢,虽然理论上解法二是O(log(m+n))的。

Java版:

public class Solution {
	public static int findKth(int A[], int B[], int k){
		if(A.length > B.length){
			return findKth(B,A,k);
		}
		if(A.length==0){
			return B[k-1];
		}
		if(k==1){
			return Math.min(A[0], B[0]);
		}
		int pa = Math.min(k/2, A.length);
		int pb = k - pa;
		if(A[pa-1]<B[pb-1]){
			return findKth(Arrays.copyOfRange(A, pa, A.length),B,k-pa );
		}else if(A[pa-1]>B[pb-1]){
			return findKth(A, Arrays.copyOfRange(B, pb, B.length),k-pb );
		}else
			return A[pa-1];
	}
    public double findMedianSortedArrays(int A[], int B[]) {
    	int len = A.length+B.length;
    	if(len%2==0){
    		return (double)(findKth(A,B,len/2)+
                            findKth(A,B,len/2+1))/2; // Do Not Forget (double) !
    	}else         
    		return findKth(A,B,len/2+1); // Not len/2 !
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值