4 寻找两个正序数组的中位数(困难)
给定两个大小分别为 m
和 n
的正序(从小到大)数组 nums1
和 nums2
。请你找出并返回这两个正序数组的 中位数 。
示例:
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
解题思路:
给定两个有序数组,要求找到两个有序数组的中位数,最直观的思路有以下两种:
-
使用归并的方式,合并两个有序数组,得到一个大的有序数组。大的有序数组的中间位置的元素,即为中位数。
-
不需要合并两个有序数组,只要找到中位数的位置即可。由于两个数组的长度已知,因此中位数对应的两个数组的下标之和也是已知的。维护两个指针,初始时分别指向两个数组的下标 00 的位置,每次将指向较小值的指针后移一位(如果一个指针已经到达数组末尾,则只需要移动另一个数组的指针),直到到达中位数的位置。
假设两个有序数组的长度分别为 m 和 n,第一种思路的时间复杂度是 O(m+n),空间复杂度是 O(m+n)。第二种思路虽然可以将空间复杂度降到 O(1),但是时间复杂度仍是 O(m+n)。
时间复杂度为log(m+n)的解法:二分查找
1、C++:归并
创建一个新的数组来存储num1和mun2拼接之后的结果,然后取其中位数。拼接时可指定两个指针,分别遍历nums1和nums2,并取nums1[i]和nums2[j]中较小的元素存储到新数组中,然后较小元素数组指针加一。时间复杂度为O(m+n)
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
vector<int> res(m+n);
int i=0,j=0,k=0;
while(i<m && j<n){
if (nums1[i]<=nums2[j]){
res[k] = nums1[i];
k++;
i++;
}
else{
res[k] = nums2[j];
k++;
j++;
}
}
while(i<m){
res[k] = nums1[i];
k++;
i++;
}
while(j<n){
res[k] = nums2[j];
k++;
j++;
}
if((m+n)%2 == 0 )
return (res[(m+n)/2]+res[(m+n-1)/2])/2.0;
else
return res[(m+n)/2];
}
};
二分查找法
解题思路:寻找两个有序数组的中位数 - 寻找两个正序数组的中位数 - 力扣(LeetCode) (leetcode-cn.com)
class Solution {
public:
int getkthnum(vector<int>& nums1, vector<int>& nums2,int k){
int m = nums1.size();
int n = nums2.size();
int i=0,j=0,p=0;
while(true){
if(i==m)
return nums2[j+k-1];
if(j==n)
return nums1[i+k-1];
if(k==1)
return min(nums1[i],nums2[j]);//k=1时,也可能有i==m、j==n条件同时存在,因此此条件放后面
p = k/2 -1;
int newi = min(i+p ,m-1);//i+p可能会溢出
int newj = min(j+p, n-1);
if (nums1[newi]<=nums2[newj]){
k=k-(newi-i+1);
i=newi+1;
}
else{
k = k-(newj-j+1);
j = newj+1;
}
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size();
int n = nums2.size();
if((m+n)%2==0)
return (getkthnum(nums1,nums2,(m+n)/2)+getkthnum(nums1,nums2,(m+n)/2+1))/2.0;
else
return getkthnum(nums1,nums2,(m+n)/2+1)
}
};
2、python
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
m = len(nums1)
n = len(nums2)
res = []
i,j = 0,0
while(i<m and j<n):
if nums1[i]<=nums2[j]:
res.append(nums1[i])
i=i+1
else:
res.append(nums2[j])
j=j+1
while(i<m):
res.append(nums1[i])
i=i+1
while(j<n):
res.append(nums2[j])
j=j+1
if (m+n)%2 ==0:
return (res[(m+n)//2]+res[(m+n-1)//2])/2
else:
return res[(m+n)//2]
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
m = len(nums1)
n = len(nums2)
res = []
res.extend(nums1)
res.extend(nums2)
res.sort()
if (m+n)%2 ==0:
return (res[(m+n)//2]+res[(m+n-1)//2])/2
else:
return res[(m+n)//2]