[LeetCode] 4. Median of Two Sorted Arrays 两个有序数组的中位数
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
You may assume nums1 and nums2 cannot be both empty.
Example 1:
nums1 = [1, 3] nums2 = [2] The median is 2.0
Example 2:
nums1 = [1, 2] nums2 = [3, 4] The median is (2 + 3)/2 = 2.5
求两个有序数组的中位数,限制了时间复杂度O(log (m+n))。
如果m+n为奇数,则中位数为AB[(m+n)/2 + 1],偶数的话,中位数为(AB[(m+n)/2] + AB[(m+n)/2 + 1])/2。
如果没有时间复杂度O(log(m+n))的要求,就可以对两个数组使用归并排序,再找到他们的中位数,直接遍历两个数组查找,用2个变量分别指向两个数组,每次取较小的一个,然后将其指针后移动,直到找到中位数,时间复杂度为O(m+n)。但不是题目想要考察的。
解法:二分搜索Binary Search,T:O(log(m+n))。两个有序数组A(m), B(n),k = (m+n)/2,奇数时找k+1大的数,偶数是找第k大和第k+1大的数在除2。找第k((m+n)/2)大的数。先在A,B中分别找第k/2大的数,如果A[k/2-1]==B[k/2-1],那么这个数就是两个数组中第k大的数。如果A[k/2-1]<B[k/2-1], 那么说明A[0]到A[k/2-1]都不可能是第k大的数,所以需要舍弃这k/2,继续从A[k/2]到A[A.length-1]继续找。当然,因为这里舍弃了A[0]到A[k/2-1]这k/2个数,那么第k大也就变成了第k-k/2个大的数了。如果 A[k/2-1]>B[k/2-1],那么说明B[0]到B[k/2-1]都不可能是第k大的数,舍弃这k/2。如此迭代或者递归操作,如果有一个数组为空了,则返回另一个数组的第k大(剩下需要二分长度)的数。如果k==1,只需返回此时所以数中排第一小的数,就返回此时A,B中第一个元素小的那个。
参考:爱做饭的小莹子
public
class
Solution {
public
double
findMedianSortedArrays(
int
A[],
int
B[]) {
int
len = A.length + B.length;
if
(len %
2
==
1
) {
return
findKth(A,
0
, B,
0
, len /
2
+
1
);
}
return
(
findKth(A,
0
, B,
0
, len /
2
) + findKth(A,
0
, B,
0
, len /
2
+
1
)
) /
2.0
;
}
public
static
int
findKth(
int
[] A,
int
A_start,
int
[] B,
int
B_start,
int
k){
if
(A_start >= A.length) {
return
B[B_start + k -
1
];
}
if
(B_start >= B.length) {
return
A[A_start + k -
1
];
}
if
(k ==
1
) {
return
Math.min(A[A_start], B[B_start]);
}
int
A_key = A_start + k /
2
-
1
< A.length
? A[A_start + k /
2
-
1
]
: Integer.MAX_VALUE;
int
B_key = B_start + k /
2
-
1
< B.length
? B[B_start + k /
2
-
1
]
: Integer.MAX_VALUE;
if
(A_key < B_key) {
return
findKth(A, A_start + k /
2
, B, B_start, k - k /
2
);
}
else
{
return
findKth(A, A_start, B, B_start + k /
2
, k - k /
2
);
}
}
}
Python:
class
Solution:
# @return a float
# @line20 must multiply 0.5 for return a float else it will return an int
def
getKth(
self
, A, B, k):
lenA
=
len
(A); lenB
=
len
(B)
if
lenA > lenB:
return
self
.getKth(B, A, k)
if
lenA
=
=
0
:
return
B[k
-
1
]
if
k
=
=
1
:
return
min
(A[
0
], B[
0
])
pa
=
min
(k
/
2
, lenA); pb
=
k
-
pa
if
A[pa
-
1
] <
=
B[pb
-
1
]:
return
self
.getKth(A[pa:], B, pb)
else
:
return
self
.getKth(A, B[pb:], pa)
def
findMedianSortedArrays(
self
, A, B):
lenA
=
len
(A); lenB
=
len
(B)
if
(lenA
+
lenB)
%
2
=
=
1
:
return
self
.getKth(A, B, (lenA
+
lenB)
/
2
+
1
)
else
:
return
(
self
.getKth(A, B, (lenA
+
lenB)
/
2
)
+
self
.getKth(A, B, (lenA
+
lenB)
/
2
+
1
))
*
0.5
Python:
class
Solution(
object
):
def
findMedianSortedArrays(
self
, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
len1, len2
=
len
(nums1),
len
(nums2)
if
(len1
+
len2)
%
2
=
=
1
:
return
self
.getKth(nums1, nums2, (len1
+
len2)
/
2
+
1
)
else
:
return
(
self
.getKth(nums1, nums2, (len1
+
len2)
/
2
)
+
\
self
.getKth(nums1, nums2, (len1
+
len2)
/
2
+
1
))
*
0.5
def
getKth(
self
, A, B, k):
m, n
=
len
(A),
len
(B)
if
m > n:
return
self
.getKth(B, A, k)
left, right
=
0
, m
while
left < right:
mid
=
left
+
(right
-
left)
/
2
if
0
<
=
k
-
1
-
mid < n
and
A[mid] >
=
B[k
-
1
-
mid]:
right
=
mid
else
:
left
=
mid
+
1
Ai_minus_1
=
A[left
-
1
]
if
left
-
1
>
=
0
else
float
(
"-inf"
)
Bj
=
B[k
-
1
-
left]
if
k
-
1
-
left >
=
0
else
float
(
"-inf"
)
return
max
(Ai_minus_1, Bj)
C++:
class
Solution {
public
:
double
findKth(vector<
int
>& A, vector<
int
>& B,
int
A_st,
int
B_st,
int
k) {
// 边界情况,任一数列为空
if
(A_st >= A.size()) {
return
B[B_st + k - 1];
}
if
(B_st >= B.size()) {
return
A[A_st + k - 1];
}
// k等于1时表示取最小值,直接返回min
if
(k == 1)
return
min(A[A_st], B[B_st]);
int
A_key = A_st + k / 2 - 1 >= A.size() ? INT_MAX : A[A_st + k / 2 - 1];
int
B_key = B_st + k / 2 - 1 >= B.size() ? INT_MAX : B[B_st + k / 2 - 1];
if
(A_key < B_key){
return
findKth(A, B, A_st + k / 2, B_st, k - k / 2);
}
else
{
return
findKth(A, B, A_st, B_st + k / 2, k - k / 2);
}
}
double
findMedianSortedArrays(vector<
int
>& nums1, vector<
int
>& nums2) {
int
sum = nums1.size() + nums2.size();
double
ret;
if
(sum & 1) {
ret = findKth(nums1, nums2, 0, 0, sum / 2 + 1);
}
else
{
ret = ((findKth(nums1, nums2, 0, 0, sum / 2)) +
findKth(nums1, nums2, 0, 0, sum / 2 + 1)) / 2.0;
}
return
ret;
}
};
All LeetCode Questions List 题目汇总