题目描述
一、思路
最简单的思路就是从两个数组头/尾开始归并的计数。但是这样时间复杂度0(m+n);并不满足要求。
我们利用二分查找 log 时间复杂度的优势。只要单调就能二分
即:
- 寻找两个排序数组中第K个数,先从左边取K/2个数,小的那一边的k/2都不可能是第K个数了,于是排除。
- 更新K=k-k/2,也就是在剩下的数组中,找到第 新K的数字。
- 直到K==1,那么取当前还剩余的数组中开头处偏小的。
就像上图:
- 找第7个元素,那么两个指针都指向k/2 = 3 的位置。
- 3<4,说明B中前三个肯定不能是第7个元素。
- 抛掉B中前三个,我们开始在剩下的元素中,找第4个了。
- 3<5,说明A中前两个也肯定不是剩下的里面第4个元素。
- 抛掉A中前两个,我们开始在剩下的元素中,找第2个了.
- 4<=4,随便抛掉一个4,我们从剩下的元素中找第1个。
10.4<9,说明我们要的中位数就是4
这么看起来是不是和最简单的归并计数下来差不多,只是每次舍弃的多了些而已。
二、难点:
1、中位数:和是奇数和是偶数怎么办
就像上面的图。13个数据,中位数就是第7个数。
如果是14个数,那么就找一下第七个数,然后再顺着找第八个数。然后取平均即可。
三、代码
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int length = nums1.size() + nums2.size();
int k = (length+1) >> 1;
bool first =true;
if (length & 1)
first = false;
int temp,temp2=0;
//find NO.K
int base1 = 0, base2 = 0;
int offset1 = 0, offset2 = 0;
while (1)
{
offset1 = offset2 = (k >> 1);
if (base1 == nums1.size())
{
temp = nums2[base2 + k-1];
base2+= k ;
break;
}
else if (base2 == nums2.size())
{
temp = nums1[base1 + k-1];
base1+= k ;
break;
}
else if (base1 + offset1 -1>= (int)nums1.size())
{
offset1 = nums1.size() - base1;
offset2 = k - offset1;
}
else if (base2 + offset2 -1>= (int)nums2.size())
{
offset2 = nums2.size() - base2;
offset1 = k - offset2;
}
if (k == 1)
{
if (nums1[base1 + offset1] <= nums2[base2 + offset2])
{
temp = nums1[base1 + offset1];
base1++;
}
else
{
temp = nums2[base2 + offset2];
base2++;
}
break;
}
if (nums1[base1 + offset1 - 1] <= nums2[base2 + offset2-1])
{
base1 += offset1;
k -= offset1;
}
else
{
base2 += offset2 ;
k -= offset2;
}
}
if (length & 1)
return temp;
else
{
if (base1 == nums1.size())
{
temp += nums2[base2];
}
else if (base2 == nums2.size())
{
temp += nums1[base1];
}
else
temp+= min(nums1[base1], nums2[base2]);
return temp / 2.0;
}
}
};
考察的点:
- 二分查找
- 归并