您的位置:首页 > 其它

Median of Two Sorted Arrays

2016-09-12 16:23 78 查看

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

Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0


Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5


题目要求找到两个已经排好序的数组中的中位数,最简单的想法是用归并排序,把两个数组合并成一个数组,然后就可以跟据下标得到中位数。但是显然这个算法的时间复杂度不符合题目的要求。我刚开始也想不到一个符合题目要求的算法,但是看到了一个关于这道题的提示以后,我就想到了可以把这道题转换成一个求第K小的数的问题。

找第K小数的过程用函数findKth来完成,利用分治策略,每次递归调用这个函数时,减少K/2-1个元素,因为在某个数组中的第k/2-1个元素比另一个数组中相同下标的元素小,那么这个数组中的前k/2-1个元素一定是在所有数中前K小的数,那么我们每次递归就可以不考虑这部分的数,也就是说不断地把数组下标较小的数排除。在函数中,分别用low1, low2来记录当前两个数组的下限,每次排除一些元素时,只需要改变数组的下限即可。也就是说在下限以前的元素已经不是当前数组的元素了,我们不再需要考虑这些元素。

实际的实现方法是每次都比较两个数组中第k/2-1个元素,然后排除较小的k/2-1个元素,以排除后的数组作为新的数组调用findKth函数。实现过程中有一些细节是需要注意的,就是要保证数组不会越界,而且要算清楚每次排除元素的个数,然后对应地减少k的值。当某个数组中的全部元素都被排除了,就要进行一次特判,直接排除另一个数组中的前k-1个元素。递归结束的条件就是k=1,这时只需要在两个数组的下限中选取较小的数即可。

当寻找第K小的元素的函数完成以后,找中位数就是相当简单的事情了。

在这个算法中,每次递归都减少了K/2-1个元素,所以时间复杂度是符合题目要求的O(log(m+n))的。

以下是实现的源代码:

double findKth(vector<int>& nums1, int low1,vector<int>& nums2,int low2,int k)
{
if(k==1)
{
if(low1>=nums1.size()) return nums2[low2];
if (low2>=nums2.size()) return nums1[low1];
return min(nums1[low1],nums2[low2]);
}
if(low1>=nums1.size()) return findKth(nums1,low1,nums2,low2+k-1,1);
if(low2>=nums2.size()) return findKth(nums1,low1+k-1,nums2,low2,1);
int n1=k/2-1,n2=k/2-1;
int t1=k/2-1+low1,t2=k/2-1+low2;
if(t1>=nums1.size())
{
t1=nums1.size()-1;
n1=t1-low1;
}
if(t2>=nums2.size())
{
t2=nums2.size()-1;
n2=t2-low2;
}
if(nums1[t1]<=nums2[t2]) return findKth(nums1,low1+n1+1,nums2,low2,k-n1-1);
else return findKth(nums1,low1,nums2,low2+n2+1,k-n2-1);
}

class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
if((nums1.size()+nums2.size())%2==1) return findKth(nums1,0,nums2,0,(nums1.size()+nums2.size())/2+1);
else return (findKth(nums1,0,nums2,0,(nums1.size()+nums2.size())/2+1)+findKth(nums1,0,nums2,0,(nums1.size()+nums2.size())/2))/2.0;
}
};

                                                                          
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: