您的位置:首页 > 其它

求两个有序非等长数组中位数

2016-01-14 16:38 387 查看
本博客所用算法是受另外一篇博客所启发,但该博主给出的代码很多边界条件和n+m为偶数的情况未考虑到,这里我做了一定的完善。

原题如下:

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

大致意思是有两个有序数组nums1和nums2,长度分别为m和n,要求找到它们合并之后的中位数并且总共的是时间效率应该为O(log(m+n))。

先看看中位数的定义,一个长度为n的数组,如果n为奇数,则数组中有(n-1)/2个元素比中位数小。如果n为偶数,则数组张有n/2个元素比上中位数小,n/2-1个元素比下中位数小。

题目要求从nums1和nums2中找出中位数,我们可以先从nums1中查找。先考虑n+m为奇数的情况,c=(m+n-1)/2,我们的查找区间应该为[nums1[0],nums1[m-1]],我们取其中间的数nums1[p],与nums2[c-p-1]和nums2[c-p]做比较。

这里需要注意的是,如果p>c,说明num1[p]偏大,我们应该调整查找区间为[nums1[0],nums1[p-1]]。如果p==c,并且此时nums1[p]<=nums2[0],那么nums1[p]就是我们所要找的中位数,否则查找区间改为[nums1[0],nums1[p-1]]。

只剩下p<c的情况需要讨论了,如果num1[p]<nums2[c-p-1],说明num1[p]偏小,查找区间改为[num1[p+1],nums1[m-1]]。否则再讨论(c-p)和n的大小关系来确定查找范围。

在n+m为偶数的情况,只需要把c加1,求两次结果即可。

代码如下,已通过测验。本人刚学习C++,写的可能比较繁琐,望见谅。

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int result1 = 0;
int result2=0;
int m = nums1.size();
int n = nums2.size();
if (n == 0)
{
if (m % 2 == 1)
{
return nums1[(m + 1) / 2 - 1];
}
else
{
return (nums1[m / 2 - 1] + nums1[m / 2]) / 2.0;
}
}
if (m == 0)
{
if (n % 2 == 1)
{
return nums2[(n + 1) / 2 - 1];
}
else
{
return (nums2[n / 2 - 1] + nums2[n / 2]) / 2.0;
}
}
if ((n + m) % 2 == 1)
{
return findmedian(nums1, nums2, 0, m - 1);
}
else
{
result1 = findmedian(nums1, nums2, 0, m - 1);
result2 = findmedian_1(nums1, nums2, 0, m - 1);
return (result1 + result2) / 2.0;
}
}
int findmedian(vector<int>& nums1, vector<int>& nums2, int begin, int end)
{
int m = nums1.size();
int n = nums2.size();
double c = ceil((double)(n + m) / 2.0) - 1;
int p = ceil((double)(begin + end) / 2.0);
if (nums2[0] >= nums1[m - 1])
{
if (c >= m)
return nums2[c - m];
if (c < m)
return nums1[c];
}
if (nums1[0] >= nums2[n - 1])
{
if (c >= n)
return nums1[c - n];
if (c < n)
return nums2[c];
}
if (begin>end)
return findmedian(nums2, nums1, 0, n - 1);
if (c<p)
{
return findmedian(nums1, nums2, begin, p - 1);
}
else if((c-p)>0)
{
if (nums1[p]<nums2[c - p - 1])
return findmedian(nums1, nums2, p + 1, end);
else{
if ((c - p) >n)
return findmedian(nums1, nums2, p + 1, end);
else
{
if((c-p)==n)
{
if(nums1[p]>=nums2[n-1])
return nums1[p];
else
return findmedian(nums1,nums2,p+1,end);
}
else if(nums1[p]>=nums2[c-p-1]&&nums1[p]<=nums2[c-p])
return nums1[p];
else if(nums1[p]>nums2[c-p])
return findmedian(nums1, nums2, begin, p - 1);
}
}
}
else if(c==p)
{
if(nums1[p]<=nums2[0])
return nums1[p];
else
return  findmedian(nums1, nums2, begin, p - 1);
}
}
int findmedian_1(vector<int>& nums1, vector<int>& nums2, int begin, int end)
{
int m = nums1.size();
int n = nums2.size();
double c = ceil((double)(n + m) / 2.0);
int p = ceil((double)(begin + end) / 2.0);
if (nums2[0] >= nums1[m - 1])
{
if (c >= m)
return nums2[c - m];
if (c < m)
return nums1[c];
}
if (nums1[0] >= nums2[n - 1])
{
if (c >= n)
return nums1[c - n];
if (c < n)
return nums2[c];
}
if (begin>end)
return findmedian_1(nums2, nums1, 0, n - 1);
if (c<p)
{
return findmedian_1(nums1, nums2, begin, p - 1);
}
else if((c-p)>0)
{
if (nums1[p]<nums2[c - p - 1])
return findmedian_1(nums1, nums2, p + 1, end);
else{
if ((c - p) >n)
return findmedian_1(nums1, nums2, p + 1, end);
else
{
if((c-p)==n)
{
if(nums1[p]>=nums2[n-1])
return nums1[p];
else
return findmedian_1(nums1,nums2,p+1,end);
}
else if(nums1[p]>=nums2[c-p-1]&&nums1[p]<=nums2[c-p])
return nums1[p];
else if(nums1[p]>nums2[c-p])
return findmedian_1(nums1, nums2, begin, p - 1);
}
}
}
else if(c==p)
{
if(nums1[p]<=nums2[0])
return nums1[p];
else
return  findmedian_1(nums1, nums2, begin, p - 1);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: