Median of Two Sorted Arrays

There are two sorted arrays A and B 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)).

只看懂了答案:

public class Solution {
    public double findMedianSortedArrays(int A[], int B[]) {
        int len = A.length + B.length;
        if (len % 2 == 0) {
            return (findKth(A, 0, B, 0, len / 2) + findKth(A, 0, B, 0, len / 2 + 1)) / 2.0 ;
        } else {
            return findKth(A, 0, B, 0, len / 2 + 1);
        }
    }
    
    // find kth number of two sorted array
    public static int findKth(int[] A, int A_start, int[] B, int B_start, int k){		
		if(A_start >= A.length) 
			return B[B_start + k - 1];
		if(B_start >= B.length)
			return A[A_start + k - 1];

		if (k == 1)
			return Math.min(A[A_start], B[B_start]);
		
		int A_key = A_start + k / 2 - 1 < A.length
		            ? A[A_start + k / 2 - 1]
		            : Integer.MAX_VALUE;
		int B_key = B_start + k / 2 - 1 < B.length
		            ? B[B_start + k / 2 - 1]
		            : Integer.MAX_VALUE; 
		
		if (A_key < B_key) {
			return findKth(A, A_start + k / 2, B, B_start, k - k / 2);
		} else {
			return findKth(A, A_start, B, B_start + k / 2, k - k / 2);
		}
	}
}

分析:

// 这道题的方法是每次排除 k/2 个元素,则(logk)次便可以找到要求的元素,k=m+n,即 O(log(m+n))
// 整个程序多次涉及到k/2 + 1 等操作,处理需要谨慎
// 同时注意 (k- k/2)不一定等于 k/2, 不要写错
public class Solution {
    public double findMedianSortedArrays(int A[], int B[]) {
        int len = A.length + B.length;
/**
 * 首先要确定的是元素的总数是even or odd
 * even 则求中间两个数的average value, 注意返回值是double 类型,除数是 2.0,如果是2的话,出错
 * odd 则求第 (len/2 +1)个数
 */
        if (len % 2 == 0) {
            return (findKth(A, 0, B, 0, len / 2) + findKth(A, 0, B, 0, len / 2 + 1)) / 2.0 ;
        } else {
            return findKth(A, 0, B, 0, len / 2 + 1);
        }
    }
    
    // find kth number of two sorted array
    public static int findKth(int[] A, int A_start, int[] B, int B_start, int k){
/**
 * 下面两个if是处理:
 * 一个数组长度为0,或者已经走到末尾了,则第k个元素只可能在第二个数组中,则从第二个数组中取
 * 这种情况同时说明 A.length < (A.length + B.length)/2,并且A的所有元素都在要求的median之前
 */
		if(A_start >= A.length) 
			return B[B_start + k - 1];
		if(B_start >= B.length)
			return A[A_start + k - 1];
/**
 * 由于上面的if已经check了 当A或B的length为0的情况,则下面可以保证A[A_start], B[B_start]一定是存在的
 * 所以当k等于1的时候,要查找的元素肯定是A[A_start], B[B_start]其中一个 
 */
		if (k == 1)
			return Math.min();
/**
 * 下面的操作:
 * 要找A和B的第k小元素,每次在A中取前k/2个元素,	每次在B中取前k/2个元素,则一定可以保证这两组中有一组是一定小于
 * 要查找的第k个元素。
 * eg,k=10,我们取了A中前5个,B中前5个,则肯定可以保证有一组数一定是在 merge(A,B)的第10个数之前的
 * 那么用来判断这5(即)个数是属于A的还是B的,则用 A_key和B_key来进行比较
 * eg a: 1, 3, 5, 7, 9, 11, 13, 15, 17, 19
 * 	  b: 2, 4, 6, 8, 10, 12, 14, 16, 18, 20
 * 此时 A_key = 9, B_key = 10.那么a的前5个数 肯定属于merge(a,b)的前10个数之前,
 * 所以下次查找,对于a数组,就可以从a的第六个元素开始找,这时候要找的是 剩下数的 第 10-(10/2)个元素即可
 *  
 *   
 * 当A_key 或者 B_key 为MAX_VALUE 的情况:
 * a(3个元素):  1,2,100	
 * b(17个元素):3,4,5,6,7,8,9,20,21,22,23,,,,,,
 * 则median是merge(a,b)的第10个元素
 * 此时,对a取5个,对b取5个。但是a一共只有三个元素,则一共只取了8个元素,
 * 那么此时,肯定可以保证的是 b取的前5个元素肯定是在前10个中的(因为假设取的这8个都是最小的了,
 * 那么还需要往后再找两个,肯定也是在b[4](b的第5个原色)的后面。所以 b[0]-b[4]是肯定小于media 的)
 */
		int A_key = A_start + k / 2 - 1 < A.length
		            ? A[A_start + k / 2 - 1]
		            : Integer.MAX_VALUE;
		int B_key = B_start + k / 2 - 1 < B.length
		            ? B[B_start + k / 2 - 1]
		            : Integer.MAX_VALUE; 
		
		if (A_key < B_key) {
			return findKth(A, A_start + k / 2, B, B_start, k - k / 2);
		} else {
			return findKth(A, A_start, B, B_start + k / 2, k - k / 2);
		}
	}
}




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 经导师精心指导并认可、获 98 分的毕业设计项目!【项目资源】:微信小程序。【项目说明】:聚焦计算机相关专业毕设及实战操练,可作课程设计与期末大作业,含全部源码,能直用于毕设,经严格调试,运行有保障!【项目服务】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值