自从上次打完icpc省赛,我很久没有做算法题了,这还是我首次做leetCode的题。我一上来看到了这道题。这道题虽然是hard难度,一开始我以为不难,后来发现要用到二分查找第k个数。以下为题目地址:
https://leetcode.com/problems/median-of-two-sorted-arrays/description/
这道题的大意就是给两个从小到大排序的数组,然后算这个两个数组里面所有数的中位数。其实这道题根本不需要用二分查找就能过(如果忽视O(log(m+n))的条件),只要用利用类似于归并的思想,利用两个变量指向两个数组中的数,沿着两个数组从前往后遍历。并且不断比较两个数组中数的大小,以达到从小到大遍历的效果。然后取中位数即可。这里需要分类讨论个数是奇数和偶数的情况。(后面给出了二分查找的算法)
下面给出提交代码:
#include <bits/stdc++.h>
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
double median, median2;
int n1=0, n2=0, i, sum, s1, s2;
s1 = nums1.size();
s2 = nums2.size();
sum = s1 + s2;
if(sum%2)
{
for(i=0;i<(sum+1)/2;i++)
{
if(n1<s1&&(n2>=s2||nums1[n1]<nums2[n2]))
{
median = nums1[n1];
n1++;
}
else
{
median = nums2[n2];
n2++;
}
}
return median;
}
else
{
for(i=0;i<sum/2+1;i++)
{
if(n1<s1&&(n2>=s2||nums1[n1]<nums2[n2]))
{
median2 = median;
median = nums1[n1];
n1++;
}
else
{
median2 = median;
median = nums2[n2];
n2++;
}
}
return (median+median2)/2;
}
}
};
代码中需要注意的是vector有可能是空的。一开始没有特别注意这一点,导致了两次RE。然后对于数组是空的情况可以通过&&和||来将后面的表达式”短路“。
if(n1<s1&&(n2>=s2||nums1[n1]<nums2[n2]))
下面给出运行结果
下面这种方法利用了二分查找,其实就是找两个数组之间第k大的数,只需要每次查询两个数组的k/2个数并比较,抛弃其中k/2个数就可以了(因为中位数不在那k个数里),然后可以通过递归解决。
#include <bits/stdc++.h>
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int s1,s2,sum;
s1 = nums1.size();
s2 = nums2.size();
sum = s1 + s2;
//cout<<sum<<endl;
if(sum%2)
return findMedianSortedArraysK(nums1,nums2,0,0,(sum+1)/2);
else
return (findMedianSortedArraysK(nums1,nums2,0,0,sum/2+1)+findMedianSortedArraysK(nums1,nums2,0,0,sum/2))/2;
}
double findMedianSortedArraysK(vector<int>& nums1, vector<int>& nums2, int f1, int f2, int k)
{
int s1, s2;
s1 = nums1.size();
s2 = nums2.size();
if(f1>=s1)
return nums2[f2+k-1];
if(f2>=s2)
return nums1[f1+k-1];
if(k==1)
return min(nums1[f1], nums2[f2]);
if(f1+k/2-1>=s1)
return findMedianSortedArraysK(nums1,nums2,f1,f2+k/2,k-k/2);
if(f2+k/2-1>=s2)
return findMedianSortedArraysK(nums1,nums2,f1+k/2,f2,k-k/2);
if(nums1[f1+k/2-1]<=nums2[f2+k/2-1])
return findMedianSortedArraysK(nums1,nums2,f1+k/2,f2,k-k/2);
else
return findMedianSortedArraysK(nums1,nums2,f1,f2+k/2,k-k/2);
}
};
但很奇怪的是,这个算法比上面的归并还要慢。。。我觉得可能是因为常数项太大(递归比循环慢),以及测试样例不够大。