leetcode——Median of Two Sorted Array

原题为:算法

There are two sorted arrays nums1 and nums2 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)).数组

好吧,我是普通青年,第一反应就是使用Merge两个数字的思想,直接找到中位数。可是这个算法的复杂度是O(m+n)。ide

leetcode给这道题打上的标签是divide and conquer以及binary search。其实我以为这个标签有点误导性。百思不得其解以后看了关于这道题的discussion,看完以后不由感叹:我数学没学好。编码

这道题的解题思路是这样子的:code

该方法的核心是将原问题转变成一个寻找第k小数的问题(假设两个原序列升序排列),这样中位数其实是第(m+n)/2小的数。因此只要解决了第k小数的问题,原问题也得以解决。递归

首先假设数组A和B的元素个数都大于k/2,咱们比较A[k/2-1]和B[k/2-1]两个元素,这两个元素分别表示A的第k/2小的元素和B的第k/2小的元素。这两个元素比较共有三种状况:>、<和=。若是A[k/2-1]<B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并以后的前k小的元素中。换句话说,A[k/2-1]不可能大于两数组合并以后的第k小值,因此咱们能够将其抛弃。而后在两个数组剩下的元素里寻找第k-(k/2)大的元素(经过递归的方式)。leetcode

当A[k/2-1]>B[k/2-1]时存在相似的结论。数学

当A[k/2-1]=B[k/2-1]时,咱们已经找到了第k小的数,也即这个相等的元素,咱们将其记为m。因为在A和B中分别有k/2-1个元素小于m,因此m便是第k小的数。(这里可能有人会有疑问,若是k为奇数,则m不是中位数。这里是进行了理想化考虑,在实际代码中略有不一样,是先求k/2,而后利用k-k/2得到另外一个数。)it

如何证实以上的规律是数学书里的内容,这里不作太多介绍。io

在实际的编码过程当中,咱们须要考虑以下边界条件:

    1. 若是m或者n为0,直接返回A[k-1]或者B[k-1];

    2. 若是k为1,那么返回A[0]或者B[0]当中较小的一个;

    3. 若是A[k/2-1] == B[k/2-1],那么直接返回两个数中的任何一个。

代码以下:

class Solution 
{
public:
	double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) 
	{
		int m = nums1.size();
		int n = nums2.size();
		//cout << m << " " << n << endl;
		if ((m+n)%2 == 0)
		{
			//cout << "even" << endl;
			return (findKthNum(nums1, nums2, (m + n) / 2) + findKthNum(nums1, nums2, (m + n) / 2 + 1))/2;
		}
		else
		{
			//cout << "odd" << endl;
			return findKthNum(nums1, nums2, (m + n) / 2 + 1);
		}
	}

	int min(int a, int b)
	{
		if (a < b)
		{
			return a;
		}
		else
		{
			return b;
		}
	}

	double findKthNum(vector<int>& nums1, vector<int>& nums2, int k)
	{
	    if (nums1.size() > nums2.size())
		{
			return findKthNum(nums2, nums1, k);  //注意nums1的size必定要比nums2小,否则会发生溢出错误
		}
		//当m或者n为0时
		if (nums1.size() == 0)
		{
			if (k <= nums2.size())
			{
				return nums2[k - 1];
			}
			else
			{
				return nums2[nums2.size() - 1];
			}
		}
		else if (nums2.size() == 0)
		{
			if (k <= nums1.size())
			{
				return nums1[k - 1];
			}
			else
			{
				return nums1[nums1.size() - 1];
			}
		}
		if (k == 1)
		{
			return min(nums1[0], nums2[0]);
		}
		int offset_1 = min(k / 2, nums1.size());
		int offset_2 = k - offset_1;
		vector<int> new_nums1, new_nums2;
		int i = 0;
		if (nums1[offset_1-1] == nums2[offset_2-1])
		{
			return nums1[offset_1-1];
		}
		else if (nums1[offset_1-1] < nums2[offset_2-1])
		{
			for (vector<int>::iterator it = nums1.begin(); it != nums1.end(); it++)
			{
				if (i >= offset_1)
				{
					new_nums1.push_back(*it);
				}
				i++;
			}
			return findKthNum(new_nums1, nums2, k - offset_1);
		}
		else
		{
			for (vector<int>::iterator it = nums2.begin(); it != nums2.end(); it++)
			{
				if (i >= offset_2)
				{
					new_nums2.push_back(*it);
				}
				i++;
			}
			return findKthNum(nums1, new_nums2, k - offset_2);
		}
	}
};
相关文章
相关标签/搜索