Question
ref: https://leetcode.cn/problems/median-of-two-sorted-arrays/
给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的 中位数 。
算法的时间复杂度应该为 O ( l o g ( m + n ) ) O(log (m+n)) O(log(m+n)) 。
示例 1:
输入: n u m s 1 = [ 1 , 3 ] , n u m s 2 = [ 2 ] nums1 = [1,3], nums2 = [2] nums1=[1,3],nums2=[2]
输出: 2.00000 2.00000 2.00000
解释:合并数组 = [ 1 , 2 , 3 ] = [1,2,3] =[1,2,3] ,中位数 2 2 2
示例 2 2 2:
输入: n u m s 1 = [ 1 , 2 ] , n u m s 2 = [ 3 , 4 ] nums1 = [1,2], nums2 = [3,4] nums1=[1,2],nums2=[3,4]
输出: 2.50000 2.50000 2.50000
解释:合并数组 = [ 1 , 2 , 3 , 4 ] = [1,2,3,4] =[1,2,3,4] ,中位数 ( 2 + 3 ) / 2 = 2.5 (2 + 3) / 2 = 2.5 (2+3)/2=2.5
提示:
n u m s 1. l e n g t h = = m n u m s 2. l e n g t h = = n 0 < = m < = 1000 0 < = n < = 1000 1 < = m + n < = 2000 − 1 0 6 < = n u m s 1 [ i ] , n u m s 2 [ i ] < = 1 0 6 \begin{align*} nums1.length == m \\ nums2.length == n \\ 0 <= m <= 1000 \\ 0 <= n <= 1000 \\ 1 <= m + n <= 2000 \\ -10^6 <= nums1[i], nums2[i] <= 10^6 \\ \end{align*} nums1.length==mnums2.length==n0<=m<=10000<=n<=10001<=m+n<=2000−106<=nums1[i],nums2[i]<=106
Answers1
The following code is my answer. but the space complexity is higher than other leet-coder and the rank of the time complexity is around of 25%. We need to further improve the answer quality and make it better.
#include<iostream>
#include<vector>
using namespace std;
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
vector<int> all_num(0);
int i1 = 0;
int i2 = 0;
int pos = 0;
double result = 0;
// merge two order list into single order list.
// using nums1.size() to achieve the length of nums1.
while (i1 < nums1.size() && i2 < nums2.size())
{
if (nums1[i1] <= nums2[i2])
{
// append a integer to the end of all_num array
all_num.push_back(nums1[i1]);
i1++;
}
else
{
all_num.push_back(nums2[i2]);
i2++;
}
}
while(i1 < nums1.size())
{
all_num.push_back(nums1[i1]);
i1++;
}
while (i2 < nums2.size())
{
all_num.push_back(nums2[i2]);
i2++;
}
if ((i1 + i2) % 2 == 0)
{
// warning: the result can rounded down(向下取整) with integer division
pos = (i1 + i2) / 2;
result = (all_num[pos] + all_num[pos - 1]) / 2.0;
}
else
{
pos = (i1 + i2) / 2;
result = all_num[pos];
}
return result;
}
int main()
{
vector<int> nums1 = { 0,1,3 };
vector<int> nums2 = { 2, 4};
cout << findMedianSortedArrays(nums1, nums2) << endl;
return 0;
}
Knowledge Corner
- the int type is converted to float or double
int pos = 0;
float pos_f = pos;
\\or
cout << (float) pos << endl;
reference url
Cpp vector https://blog.csdn.net/qiancm/article/details/119611928
Answer 2
The following code don’t need to open more space to save the addition arrays, and just use pointer i and pointer j to solve this problem, the space complexity is converted from O ( m + n ) O(m+n) O(m+n) to O ( 1 ) O(1) O(1).
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
// 定义 i j 2个指针分别指针2个数组
// 定义 l r 分别用来保存中位数;奇数个,只会用到 l 变量;偶数,会用到 l r 变量
int m = nums1.size();
int n = nums2.size();
int i = 0, j = 0;
int l = 0, r = 0;
for (int x = 0; x <= (m + n) / 2; x++) {
l = r;
r = (i < m && (j >= n || nums1[i] < nums2[j])) ?
nums1[i++] : nums2[j++];
}
return (m + n) & 1 ? r : (l + r) / 2.0;
}
};
Knowledge Corner
reference url:
bit operator: https://blog.csdn.net/weixin_43736974/article/details/84543970
Answer 3
We further improve the time complexity from O ( m + n ) O(m+n) O(m+n) to O ( l o g ( m + n ) ) O(log(m+n)) O(log(m+n)). The below is solution. The division method is used.
The main thought of the method is the problems is regarded as the question to find the k k k-th biggest element in both arrays. And the pointer i i i and pointer j j j satisfy the following equation.
i
+
j
=
k
i+j=k
i+j=k
n
u
m
s
1
[
i
−
1
]
<
=
n
u
m
s
2
[
j
]
&
&
n
u
m
s
2
[
j
−
1
]
<
=
n
u
m
s
1
[
i
]
nums1[i-1]<=nums2[j]\&\&nums2[j-1]<=nums1[i]
nums1[i−1]<=nums2[j]&&nums2[j−1]<=nums1[i]
In the end, the problem becomes
m
a
x
(
n
u
m
s
1
[
i
−
1
]
,
n
u
m
s
2
[
j
−
1
]
)
max(nums1[i-1],nums2[j-1])
max(nums1[i−1],nums2[j−1]).
we just find the proper pointer i using division method, and the pointer j is acquired by equation i + j = k i+j=k i+j=k.
class Solution {
public:
int findKthElm(vector<int>& nums1,vector<int>& nums2,int k){
assert(1<=k&&k<=nums1.size()+nums2.size());
int le=max(0,int(k-nums2.size())),ri=min(k,int(nums1.size()));
while(le<ri){
int m=le+(ri-le)/2;
if(nums2[k-m-1]>nums1[m]) le=m+1;//这为什么只写一个条件?!因为这是二分的排除条件,不是目标的符合条件,相当于排除条件,最后的结果才是符合条件的结果
else ri=m;
}//循环结束时的位置le即为所求位置,第k小即为max(nums1[le-1]),nums2[k-le-1]),但是由于le可以为0、k,所以
//le-1或者k-le-1可能不存在所以下面单独判断下
int nums1LeftMax=le==0?INT_MIN:nums1[le-1];
int nums2LeftMax=le==k?INT_MIN:nums2[k-le-1];
return max(nums1LeftMax,nums2LeftMax);
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n=nums1.size()+nums2.size();
if(n&1){//两个数组长度和为奇数
return findKthElm(nums1,nums2,(n>>1)+1);
}
else{//为偶数
return (findKthElm(nums1,nums2,n>>1)+findKthElm(nums1,nums2,(n>>1)+1))/2.0;
}
}
};
Reference:
Other Method
Other methods and some tricks can further improve the Further improve capability of the algorithm. But we don’t note them.