class Solution:
def findMedianSortedArrays(self, A: List[int], B: List[int]) -> float:
if len(A) > len(B):
return self.findMedianSortedArrays(B, A)
inf = 1e7
m, n = len(A), len(B)
# half 表示一半的数量;+1 是为了使奇数情况时,左侧数量多一个,偶数不影响;
half = (m + n + 1) // 2
l, r = 0, m # [l, r) 左闭右开区间,循环时要始终保持这个开闭原则
while l < r: # 因为是左闭右开区间,所以 l 要始终小于 r
# 这里 i 和 j 指的是数量,而不是下标,即 A 中的前 i 个数,B 中的前 j 个数;
# i + j 共同组成了“前一半”的数
i = (l + r + 1) // 2
j = half - i
# 因为 i 和 j 都是指的数量,所以下标要 -1;具体来说,i 和 j 分别把 A 和 B 划分成了如下两个区间
# 前一半包括 A[0 .. i-1] 和 B[0 .. j-1]
# 后一半包括 A[i .. m-1] 和 B[j .. n-1]
# 二分的目标是找到最大的 i 使 A[i - 1] <= B[j] 成立
if A[i - 1] <= B[j]:
l = i # [l, i-1] 区间满足要求,下一轮在 [i, r) 中继续找更大的,所以使 l = i
else:
r = i - 1 # [i-1, r) 区间不满足要求,下一轮从 [l, i-1) 继续找符合的,所以令 r = i - 1
# 退出循环时 l == r
i, j = l, half - l
# 记 m1, m2 分别表示前半部分的最大值和后半部分的最小值,根据定义
# m1, m2 = max(A[i-1],B[j-1]), min(A[i],B[j])
# 这里要注意 i=0/i=m/j=0/j=n 的情况(越界)
# i == 0 表示前一半从 A 中取 0 个数,即前一半都从 B 中取;
# i == m 表示前一半取 A 中所有数,剩下的再从 B 中取;
# j == 0, j == n 同理
a_im1 = -inf if i == 0 else A[i - 1]
a_i = inf if i == m else A[i]
b_jm1 = -inf if j == 0 else B[j - 1]
b_j = inf if j == n else B[j]
m1, m2 = max(a_im1, b_jm1), min(a_i, b_j)
return (m1 + m2) / 2 if (m + n) % 2 == 0 else m1