题目:
给定两个大小分别为 m
和 n
的正序(从小到大)数组 nums1
和 nums2
。请你找出并返回这两个正序数组的 中位数
解题
解法1:二分
找第mid小的数,先判断两个数组mid/2位置的数,小的那个数组之前的i个数都可以排除掉,然后再继续找第(mid-i)小的数,重复。
如果一个数组被排除完了,那就直接找剩下数组的第mid个数。
如果mid = 1,取未排除中小的那个数
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int total = nums1.size() + nums2.size();
if (total % 2)
return getn(nums1, nums2, (total + 1) / 2);
else
return (getn(nums1, nums2, (total + 1) / 2) +
getn(nums1, nums2, total / 2 + 1)) / 2.0;
}
int getn(vector<int>& nums1, vector<int>& nums2, int mid)
{
int index1 = 0, index2 = 0; // 当前未排除的下标
int size1 = nums1.size(), size2 = nums2.size();
while(1)
{
// 边界情况
if (index1 == size1)
return nums2[index2 + mid - 1];
if (index2 == size2)
return nums1[index1 + mid - 1];
if (mid == 1)
return min(nums1[index1], nums2[index2]);
// 正常情况
int newindex1 = min(index1 + mid / 2 - 1, size1 - 1);
int newindex2 = min(index2 + mid / 2 - 1, size2 - 1);
if (nums1[newindex1] < nums2[newindex2])
{
mid -= newindex1 - index1 + 1; //减去多排除的数!
index1 = newindex1 + 1;
}
else
{
mid -= newindex2 - index2 + 1; //减去多排除的数!
index2 = newindex2 + 1;
}
}
}
复杂度
- 时间:O(log(len1+len2))
- 空间:O(1)
解法2:双指针,找第mid个数。(时间复杂度高)
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
// 中位数就是找到第mid个数
int index1 = 0, index2 = 0;
int total = nums1.size() + nums2.size();
int mid = (total >> 1) + 1; //如果是偶数找后面那个
int pre = 0; // 用来记录前面那个数
int now = 0; // 用来记录当前的数
while (mid --)
{
pre = now;
// 一个时刻只会有一个越界,越界就取另一个
if (index1 < nums1.size() && (index2 >= nums2.size() || nums1[index1] < nums2[index2]))
now = nums1[index1++];
else
now = nums2[index2++];
}
if (total % 2)
return now;
else
return (double)(now + pre) / 2;
}
复杂度
- 时间:O((len1 + len2) / 2)
- 空间:O(1)