码迷,mamicode.com
首页 > 其他好文 > 详细

leetcode——Median of Two Sorted Array

时间:2015-08-19 17:54:35      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:

原题为:

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)。

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

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

该方法的核心是将原问题转变成一个寻找第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)大的元素(通过递归的方式)。

当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获得另一个数。)

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

在实际的编码过程中,我们需要考虑如下边界条件:

    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);
		}
	}
};


leetcode——Median of Two Sorted Array

标签:

原文地址:http://my.oschina.net/u/1047616/blog/494682

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!