LeetCode: Median of Two Sorted Arrays

题目

https://oj.leetcode.com/problems/median-of-two-sorted-arrays/


分析

如果这道题的时间复杂度要求是O(m+n)的话, 就很简单了, 直接merge之后找出中位数即可。 

如果时间复杂度要求为O(log(m+n))的话, 可以把这道题转化为求第k小的问题。
1. 如果(m+n)是奇数的话, 中位数就是第(m+n)/2+1小; 如果(m+n)是偶数, 中位数就是第(m+n)/2小和第(m+n)/2+1小的平均数。

2. 然后问题是如何求解第k小的数?

           假设有两个数组:   

           A[0], A[1], ......A[m-1]

           B[0], B[1], ......B[n-1]

           两数组合并后为

           C[0], C[1], ...... C[m+n-1]


           不妨假设m和n都大于k/2, 比较A[k/2-1]和B[k/2-1], 

           如果A[k/2-1] < B[k/2-1], 那么A[k/2-1]及其左侧的元素一定小于合并后的第k小的那个数(即C[k-1])


           为什么?

           可以通过反证来证明, 

           假设A[k/2-1]等于合并后第k小元素 (即C[k-1]), 

           那么实际最多有多少个元素比A[k/2-1]小呢? A[0], A[1]......A[k/2-2]以及B[0], B[1].......B[k/2-2], 共k-2个元素。 也就是说A[k/2-1]最好情况下是第k-1小元素(即C[k-2])

           这与假设矛盾, 因此假设不成立


           因此可以说, A[k/2-1]及其左侧元素一定小于合并后的第k小那个数, 这样就可以排除掉这一范围的数,从而缩小了问题规模。

3. 再来考虑递归基

           当A为空或者B为空时, 返回B[k-1]或A[k-1]

           当k == 1时, 返回A[0]和B[0]中较小的那个数

           当A[k/2-1] == B[k/2-1]时, 返回A[k/2-1]

           否则的话, 就递归缩小问题规模。



代码

class Solution
{
public:
	double findMedianSortedArrays(int A[], int m, int B[], int n)
	{
		if ((m + n) & 0x01)
			return findKth(A, m, B, n, (m + n) / 2 + 1);
		else
			return (findKth(A, m, B, n, (m + n) / 2) 
					+ findKth(A, m, B, n, (m + n) / 2 + 1)) / 2;
	}

	double findKth(int A[], int m, int B[], int n, int k)
	{
		if (m > n)
			return findKth(B, n, A, m, k);
		else if (m == 0)
			return B[k-1];
		else if (k == 1)
			return min(A[0], B[0]);
		else
		{
			int ALeftCount = min(k / 2, m);
			int BLeftCount = k - ALeftCount;

			if (A[ALeftCount-1] == B[BLeftCount-1])
				return A[ALeftCount-1];
			else if (A[ALeftCount-1] < B[BLeftCount-1])
				return findKth(A+ALeftCount, m-ALeftCount, 
						B, n, k-ALeftCount);
			else//A[ALeftCount-1] > B[BLeftCount-1]]
				return findKth(A, m, 
						B+BLeftCount, n-BLeftCount, k-BLeftCount);
		}
	}
};



参考

http://blog.csdn.net/yutianzuijin/article/details/11499917


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值