题目
给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0
示例 2:
nums1 = [1, 2]
nums2 = [3, 4]
则中位数是 (2 + 3)/2 = 2.5
解法1 合并数组
将两个有序数组合并到一个新的数组,相当于模拟归并排序的过程。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int len1 = nums1.size();
int len2 = nums2.size();
int start1 = 0,start2 = 0;
vector<int> result;
while(start1 < len1 || start2 < len2)
{
if(start1 >= len1)
{
result.push_back(nums2[start2++]);
}
else if(start2 >= len2)
{
result.push_back(nums1[start1++]);
}
else{
result.push_back(nums1[start1] > nums2[start2]?nums2[start2++]:nums1[start1++]);
}
}
int count = result.size();
if(count % 2 == 1)
{
double tmp = result[count/2];
return tmp;
}
else{
double tmp = result[count / 2] + result[count / 2 - 1];
return tmp / 2;
}
return -1;
}
};
解法2 求第K大个数
求有序数组的中位数可以转换成求第K大个数的问题。
具体参见
leetcode 4. 题解
每次从数组中排除k/2个必定不是中位数的元素,算法的时间复杂度为
O
(
l
o
g
k
)
O(logk)
O(logk)因为
k
∼
(
m
+
n
)
k \sim (m + n)
k∼(m+n),所以算法的时间复杂度满足题目需求。
空间复杂度
O
(
1
)
O(1)
O(1) 属于尾递归。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int len1 = nums1.size();
int len2 = nums2.size();
if(len1 + len2 % 2 == 1)
return merge_find(0,len1 - 1,nums1,0,len2 - 1,nums2,(len1 + len2 + 1)/2); // 奇数情况
else {
double sum = merge_find(0,len1 - 1,nums1,0,len2 - 1,nums2,(len1 + len2 + 1)/2) +\
merge_find(0,len1 - 1,nums1,0,len2 - 1,nums2,(len1 + len2 + 2)/2); //偶数情况
return sum/2;
}
}
double merge_find(int beg_1,int end_1,vector<int>& nums1,int beg_2,int end_2,vector<int> & nums2,int k)
{
int cur_len1 = end_1 - beg_1 + 1;
int cur_len2 = end_2 - beg_2 + 1;
if(cur_len1 == 0)
return nums2[beg_2 + k - 1];
if(cur_len2 == 0)
return nums1[beg_1 + k - 1];
if(k == 1)
{
return nums1[beg_1] < nums2[beg_2]?nums1[beg_1] : nums2[beg_2];
}
else{
int diff = k / 2;
int cur_index1 = beg_1 + diff - 1> end_1?end_1:beg_1 + diff - 1; //不能保证偏移量过界
int cur_index2 = beg_2 + diff - 1> end_2?end_2:beg_2 + diff - 1;
if(nums1[cur_index1] > nums2[cur_index2])
{
k = k - (cur_index2 - beg_2 + 1); // 因为存在cur + k/2越界问题,所以需要计算实际偏移量。
return merge_find(beg_1,end_1,nums1,cur_index2 + 1,end_2,nums2,k);
}
else {
k = k - (cur_index1 - beg_1 + 1);
return merge_find(cur_index1 + 1,end_1,nums1,beg_2,end_2,nums2,k);
}
}
}
};