您的位置:首页 > 其它

2-找两个有序数组的中位数

2017-03-19 18:54 225 查看

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

1. 步骤

假设这两个数组的大小分别为m (nums1)和n (nums2)。

首先要有最差的解法,即不考虑时间复杂度O(log(m+n))

解法1-思路:使用合并排序中的merge函数,将两个有序数组合并为一个有序数组,而后返回中位数。此时时间复杂度为O(n+m)

其次,再找较优秀的解法

解法2-思路: 时间复杂度为O(log(m+n),两个数组又是有序的数组,故考察的应该是二分查找;

2. 优化思路

题目其实可以拓展为求两个有序数组第k大元素。假设我们有一个函数可以用来返回合并数组的第k大元素,那么就变成了这样:

如果 m+n 是奇数,则找合并数组的第
(m+n)/2
大元素

如果 m+n 是偶数,则返回
(m+n)/2
大元素和第
(m+n)/2+1
大元素

如何求两个有序数组的第
k
大元素? 我们可以每次取两个数组的前
k/2
个元素,比较两个数组的第
k/2
个元素的大小,而后决定删除哪一个数组的前
k/2
个元素。因为第
k
大元素肯定不可能在第
2/k
个元素较小的那个数组的前
k/2
个元素之中
。算法步骤如下:

每一次取nums1和nums2的前k/2个元素,比较
nums1[k/2]
nums2[k/2]
的大小

if(nums1[k/2] <= nums2[k/2] )
,则删除
nums1[0~k/2]
之间的元素,第
k
个元素不可能在该区间,同时也要更新
k


反之,则删除
nums2[0~k/2]
之间的元素,更新
k


递归地进行上述操作,直到找到第
k
个元素为止

3. 容易出错的地方

基本上就是递归的终止条件,非常容易出错。要注意如下几点:

nums1.size()<k/2
nums2.size()<k/2
的时候,要如何处理?

k==1
的时候要如何处理?

上述两个条件都不满足的时候要如何处理?

每一删除数组中一个区间,数组的边界如何处理?

4. 代码如下

方法1:

class Solution1 { //时间复杂度为o( size(x1) + size(x2) )
public:
void merge(vector<int> &des,vector<int>&x1,vector<int>&x2){
int _size=des.size();
int i,j,k;
i=0;
j=0;
k=0;
while(i<x1.size() && j<x2.size() ){
if(x1[i]<x2[j]){
des[k++]=x1[i++];
}else{
des[k++]=x2[j++];
}
}

if(i<x1.size()) {
for(;i<x1.size();++i){
des[k++]=x1[i];
}
}else{
for(;j<x2.size();++j){
des[k++]=x2[j];
}
}

}

double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
vector<int> des(nums1.size()+nums2.size(),0);
merge(des,nums1,nums2);
int middle=( des.size()-1 )/2;
if(des.size()%2==0){
return double(des[middle]+des[middle+1])/2;
}else{
return des[middle];
}
}
};


方法2:

class Solution2 {
public:
// 非递归形式 边界这块不好写  不用考虑奇数偶数问题只需要返回一个值就好了
int findKth(vector<int>&nums1,int low1,int high1,vector<int>&nums2,int low2,int high2,int k){
if(low1>high1)
return nums2[low2+k-1];
if(low2>high2)
return nums1[low1+k-1];
if(k==1)
{
return min(nums1[low1],nums2[low2]);
}
int mid=k/2-1;
if( (low1+mid)>high1){
if( nums1[high1]<=nums2[low2+mid]  ){
k=k-(high1-low1+1);
return nums2[low2+k-1];
}else{
k=k-(mid+1);
low2 += mid+1;
return findKth(nums1,low1,high1,nums2,low2,high2,k);
}

}

if((low2+mid)>high2 ){
if( nums2[high2]<=nums1[low1+mid]  ){
k=k-(high2-low2+1);
return nums1[low1+k-1];
}else{
k=k-(mid+1);
low1 += mid+1;
return findKth(nums1,low1,high1,nums2,low2,high2,k);
}
}

if( nums1[ low1 + mid ] <= nums2[ low2 + mid ]) {
low1=low1+mid+1;
k=k-(mid+1);
}else{
low2=low2+mid+1;
k=k-(mid+1);
}
return findKth(nums1,low1,high1,nums2,low2,high2,k);
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int _size=nums1.size()+nums2.size();
int mid=(_size+1)/2;
double res=0;
if(_size%2==0){
res=(double)findKth(nums1,0,nums1.size()-1,nums2,0,nums2.size()-1,mid);
cout<<res<<endl;
res += (double)findKth(nums1,0,nums1.size()-1,nums2,0,nums2.size()-1,mid+1);
res=res/2;
}else{
res=(double)findKth(nums1,0,nums1.size()-1,nums2,0,nums2.size()-1,mid);
}
return res;
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: