解题思路:
- 合并数组,定位中位数;
- 二分查找;
- 公式推导(真的秀,参见官方回答)。
思路一 合并数组
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size();
int n=nums2.size();
int len=m+n;
double sum[len];
int ans1=0,ans2=0;
for(int i=0;i<len;++i)
{
if(ans1<m&&ans2<n)
{
if(nums1[ans1]<=nums2[ans2])
{
sum[i]=nums1[ans1];
ans1++;
continue;
}else
{
sum[i]=nums2[ans2];
ans2++;
continue;
}
}
if(ans1==m&&ans2<n)
{
sum[i]=nums2[ans2];
ans2++;
continue;
}
if(ans1<m&&ans2==n)
{
sum[i]=nums1[ans1];
ans1++;
continue;
}
}
double res=0;
if(len%2==0)
{
res=(sum[len/2-1]+sum[len/2])/2;
}else{
res=sum[len/2];
}
return res;
}
};
这是我能独立写出来的解法,复杂度如下:
时间复杂度 | 空间复杂度 |
O(m+n) | O(m+n) |
思路二 二分查找
nums1长度为m,nums2长度为n,查找中位数,可以转化为查找两个数组中第k大的数:
(1)数组长度为奇数:k=(m+n)/2+1;
(2)数组长度为偶数 :k=(m+n)/2,(m+n)/2+1,中位数为这两者的平均值。
可以采用二分查找的思想:
-->寻找两个数组中第k大的数:
有三种情况:
(1)nums1[k/2-1]<nums2[k/2-1]:可以排除num1[0]-nums1[k/2-1]的数;
(2)nums1[k/2-1]>nums2[k/2-1]:可以排除num2[0]-nums2[k/2-1]的数;
(3)nums1[k/2-1]=nums2[k/2-1]:可以按照(1)的方式处理。
特殊情况处理:
(1)越界;取该数组最后一位;
(2)其中一者为空;
(3)k=1;取头部较小的;
代码如下 :
class Solution {
public:
double findKthElenment(vector<int>&nums1,vector<int>&nums2,int k){
int m=nums1.size();
int n=nums2.size();
int ans1=0,ans2=0;
while(true)
{
if(ans1==m)
{
return nums2[ans2+k-1];
}
if(ans2==n)
{
return nums1[ans1+k-1];
}
if(k==1)
{
return min(nums1[ans1],nums2[ans2]);
}
int newans1=min(ans1+k/2-1,m-1);
int newans2=min(ans2+k/2-1,n-1);
if(nums1[newans1]<=nums2[newans2])
{
k-=newans1-ans1+1;
ans1=newans1+1;
}else
{
k-=newans2-ans2+1;
ans2=newans2+1;
}
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m=nums1.size();
int n=nums2.size();
if((m+n)%2!=0)
{
return findKthElenment(nums1,nums2,(m+n)/2+1);
}
else{
return (findKthElenment(nums1,nums2, (m+n)/2)+findKthElenment(nums1, nums2, (m+n)/2+1))/2;
}
}
};
这种方法我感觉我理解得还有些磕磕绊绊,复杂度如下:
时间复杂度 | 空间复杂度 |
O(log(m+n)) | O(1) |
思路三 划分数组 公式推导
存在规律可以推导,自认为通用性不大,就不深究了。
参考链接:寻找两个有序数组的中位数 - 寻找两个正序数组的中位数 - 力扣(LeetCode)
复杂度为:
时间复杂度 | 空间复杂度 |
O(m+n) | O(m+n) |
思考总结:总体思路不难,但是边界情况和分类情况较多:奇偶分类、一个数组遍历完这些...一个个拎出来讲会很麻烦,如果思路不够清晰的话,很容易就绕进去,而且写出很多的bug。
所以最好先列出大致思路和分类情况再开始写代码,边想边写会出乱子。
像找中位数转化为查找第k大数这样转化抽象思维,还需要强化练习。