解法
参考官方解法
代码
方法一:二分查找
class Solution:
def getKthElement(self, nums1, nums2, k):
m = len(nums1)
n = len(nums2)
index1 = 0
index2 = 0
while True:
if index1 == m:
return nums2[index2 + k - 1]
if index2 == n:
return nums1[index1 + k - 1]
if k == 1:
return min(nums1[index1], nums2[index2])
i = min(index1 + k // 2 - 1, m - 1)
j = min(index2 + k // 2 - 1, n - 1)
pivot1 = nums1[i]
pivot2 = nums2[j]
if pivot1 <= pivot2:
k -= i - index1 + 1 # 排除掉的元素个数
index1 = i + 1
else:
k -= j - index2 + 1
index2 = j + 1
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
m = len(nums1)
n = len(nums2)
totallen = m + n
if totallen % 2 == 0:
median = (self.getKthElement(nums1, nums2, totallen // 2) + self.getKthElement(nums1, nums2, totallen // 2 + 1)) / 2
else:
median = self.getKthElement(nums1, nums2, totallen // 2 + 1)
return median
复杂度分析
-
时间复杂度: O ( log ( m + n ) ) O(\log(m+n)) O(log(m+n)),其中 m m m 和 n n n 分别是数组 nums1 \text{nums1} nums1 和
nums2 \text{nums2} nums2 的长度。初始时有 k = ( m + n ) / 2 k=(m+n)/2 k=(m+n)/2 或
k = ( m + n ) / 2 + 1 k=(m+n)/2+1 k=(m+n)/2+1,每一轮循环可以将查找范围减少一半,因此时间复杂度是 O ( log ( m + n ) ) O(\log(m+n)) O(log(m+n))。 -
空间复杂度: O ( 1 ) O(1) O(1)。
方法二:划分数组
import sys
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
# 使nums1为长度较小的数组
if len(nums1) > len(nums2):
temp_nums = nums1
nums1 = nums2
nums2 = temp_nums
m = len(nums1)
n = len(nums2)
totalleft = (m + n + 1) // 2 # 分割线左边的元素个数
left = 0 # 二分查找左区间
right = m # 二分查找右区间
while(left < right):
# 退出循环时有left == right
i = left + (right - left + 1) // 2
j = totalleft - i
# 不满足交叉小于条件
if nums1[i-1] > nums2[j]:
right = i - 1
else:
left = i # 若区间为[left(i), right]只有两个元素,将出现死循环,因此在i的定义处需要+1
# 重新定义i, j
i = left
j = totalleft - i
nums1LeftMax = -sys.maxsize if i == 0 else nums1[i-1]
nums1RightMin = sys.maxsize if i == m else nums1[i]
nums2LeftMax = -sys.maxsize if j == 0 else nums2[j-1]
nums2RightMin = sys.maxsize if j == n else nums2[j]
if (m + n) % 2 == 0:
median = (max(nums1LeftMax, nums2LeftMax) + min(nums1RightMin, nums2RightMin)) / 2
else:
median = max(nums1LeftMax, nums2LeftMax)
return median
复杂度分析
- 时间复杂度:
O
(
log
min
(
m
,
n
)
)
)
O(\log\min(m,n)))
O(logmin(m,n))),其中
m
m
m 和
n
n
n 分别是数组
nums1
\text{nums1}
nums1 和
nums2 \text{nums2} nums2 的长度。查找的区间是 [ 0 , m ] [0, m] [0,m],而该区间的长度在每次循环之后都会减少为原来的一半。所以,只需要执行
log m \log m logm 次循环。由于每次循环中的操作次数是常数,所以时间复杂度为 O ( log m ) O(\log m) O(logm)。由于我们可能需要交换
nums1 \text{nums1} nums1 和 nums2 \text{nums2} nums2 使得 m ≤ n m \leq n m≤n,因此时间复杂度是
O ( log min ( m , n ) ) ) O(\log\min(m,n))) O(logmin(m,n)))。 - 空间复杂度: O ( 1 ) O(1) O(1)。