题目描述
给定两个大小为 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
给定代码
class Solution {
public double findMedianSortedArrays(int[] num1, int[] num2) {
}
}
题解一
暴力破解,先合并,再排序。
根据总数奇偶,取中间一个数或两个数。
全程调用API。
class Solution {
public double findMedianSortedArrays(int[] A, int[] B) {
int [] result = new int[A.length + B.length];
// 将A和B合并
System.arraycopy(A, 0, result, 0, A.length);
System.arraycopy(B, 0, result, A.length, B.length);
// 排序
Arrays.sort(result);
int len = A.length + B.length;
return (len & 1) == 0 ? (result[len / 2 - 1] + result[len / 2]) / 2.0 : result[len / 2];
}
}
时间复杂度: O ( ( n + m ) l o g ( n + m ) ) O((n + m)log(n + m)) O((n+m)log(n+m)), n n n和 m m m分别为两个数组的长度,合并耗时 O ( n + m ) O(n + m) O(n+m),排序耗时 O ( ( n + m ) l o g ( n + m ) ) O((n + m)log(n + m)) O((n+m)log(n+m))。
空间复杂度:
O
(
n
+
m
)
O(n + m)
O(n+m),开的result
数组空间为
n
+
m
n + m
n+m。
题解二
从小往大读,读到中位数时停下来并返回结果。
class Solution {
public double findMedianSortedArrays(int[] A, int[] B) {
int m = A.length;
int n = B.length;
int len = m + n;
// right记录当前遍历的数,left记录上一个数
int left = -1, right = -1;
int aStart = 0, bStart = 0;
for (int i = 0 ; i <= len / 2 ; i++)
{
left = right;
if (aStart < m && (bStart >= n || A[aStart] < B[bStart]))
{
right = A[aStart++];
}
else
{
right = B[bStart++];
}
}
if ((len & 1) == 0)
return (left + right) / 2.0;
else
return right;
}
}
时间复杂度: O ( m + n ) O(m + n) O(m+n),需要遍历 ( m + n ) / 2 (m + n) / 2 (m+n)/2次。
空间复杂度: O ( 1 ) O(1) O(1)。不需要额外开空间。
题解三
来自力扣大佬的思路:
要达到题目的
O
(
l
o
g
(
m
+
n
)
)
O(log(m + n))
O(log(m+n)),只有通过二分的方法来解决了。
题目的求中位数,可以理解为求第
k
k
k 小的数。(
k
=
(
m
+
n
)
/
2
k = (m + n)/2
k=(m+n)/2)
由于数组是有序的,其实可以每次排除
k
/
2
k / 2
k/2个数。
我们比较两个数组的第
k/2
个数字,如果 k
是奇数,向下取整。也就是比较第 3
个数字,上边数组中的 4
和下边数组中的 3
,如果哪个小,就表明该数组的前 k/2
个数字都不是第 k
小数字,所以可以排除。也就是 1,2,3
这三个数字不可能是第 7
小的数字,我们可以把它排除掉。将 1349
和 45678910
两个数组作为新的数组进行比较。
然后
k
减去排除了的数目后,在进行类似比较。每次排除大约k/2
,就能达到题目所给的复杂度要求。
具体代码没有实现。可以参考力扣题解