题目

思路
1、假定S1中存在中位数,则可用二分的方式来枚举,设为S1[mid],即S1中下标为mid的数
2、在S2中二分找到最后一个小于等于中位数S1[mid]的位置mid2
3、此时,注意到S1的[0,mid]与S2的[0,mid2],他们均小于等于S1[mid],且因为数组是非递减的,故而剩下的数都大于等于S1[mid]
4、计算S1[0,mid]和S2[0,mid2]的长度 len = mid + 1 + L2 + 1 ,设一个数组长度为n,则:
(1)若len == n,说明找到了,直接返回S1[mid]
(2)若len > n,说明中位数太大了
(3)若len < n,说明中位数太小了
5、若S1找完了,跳出二分查找了,还是没有找到,则说明中位数在S2,此时,讲S1与S2调换再来一遍即可
复杂度
时间复杂度:O(2 * log2(n) * log2(n))
空间复杂度:O(1)
相关资料
这里贴一个链接,有这道题目更全面的信息: 408史上最难算法题:两个升序数组的中位数
C++ 代码
class Solution {
int find(vector<int>& S1 , vector<int>& S2) {
int n = S1.size();
int L1 = 0, R1 = S1.size() - 1;
while (L1 <= R1) { // 二分检查每个可能的中位数
int mid = (L1 + R1) >> 1;
int L2 = 0, R2 = S2.size() - 1;
while (L2 < R2) { // 在S2中二分查找小于等于中位数S1[mid]的数的个数
int mid2 = (L2 + R2 + 1) >> 1;
if (S2[mid2] > S1[mid]) R2 = mid2 - 1;
else L2 = mid2;
}
if (S2[L2] > S1[mid]) L2--; // 说明一个都没找到,S2全都大于中位数
int len = mid + 1 + L2 + 1; // S1与S2中数的总数
if (len == n) return S1[mid];
else if (len > n) R1 = mid - 1;
else L1 = mid + 1;
}
return INT_MIN; // 作为没找到答案的标志
}
public:
int medianSearch(vector<int>& S1 , vector<int>& S2) {
int ret = find(S1, S2);
if (ret != INT_MIN) return ret;
return find(S2, S1); // 第一次没找到就反过来再找一次
}
};

2807

被折叠的 条评论
为什么被折叠?



