def find_kth(X, x_start, x_len, Y, y_start, y_len, k): if x_len == 0: return Y[y_start + k - 1] if y_len == 0: return X[x_start + k - 1] if k == 1: return min(X[x_start], Y[y_start]) i = min(k // 2, x_len) j = min(k // 2, y_len) if X[x_start + i - 1] < Y[y_start + j - 1]: return find_kth(X, x_start + i, x_len - i, Y, y_start, y_len, k - i) else: return find_kth(X, x_start, x_len, Y, y_start + j, y_len - j, k - j) def find_median(X, Y): n = len(X) median1 = find_kth(X, 0, n, Y, 0, n, n) median2 = find_kth(X, 0, n, Y, 0, n, n + 1) return (median1 + median2) / 2 # 处理输入 n = int(input("请输入n(输入-1随机生成): ")) if n == -1: import random n = random.randint(1, 10) X = sorted(random.sample(range(1, 100), n)) Y = sorted(random.sample(range(1, 100), n)) print(f"随机生成n={n}:") print("X数组:", X) print("Y数组:", Y) else: X = list(map(int, input("请输入X数组(已排序): ").split())) Y = list(map(int, input("请输入Y数组(已排序): ").split())) if len(X) != n or len(Y) != n: print("错误:数组长度不等于n") exit() print("中位数为:", find_median(X, Y))
这段Python代码用于高效地查找两个已排序数组的中位数,时间复杂度为 O(logn)。以下是详细解释:
核心功能
find_kth
函数
采用分治策略在两个有序数组中查找第 k 小的元素:- 参数说明:
X
,Y
:输入的两个有序数组。x_start
,y_start
:当前子数组的起始索引。x_len
,y_len
:当前子数组的长度。k
:目标元素的排名(第k小)。
- 终止条件:
- 如果
X
的子数组为空(x_len == 0
),直接返回Y
的第k
个元素。 - 如果
Y
的子数组为空(y_len == 0
),直接返回X
的第k
个元素。 - 如果
k == 1
,返回X[x_start]
和Y[y_start]
中的较小值。
- 如果
- 分治逻辑:
- 计算要比较的元素位置:
i = min(k//2, x_len)
和j = min(k//2, y_len)
。 - 比较
X[x_start + i - 1]
和Y[y_start + j - 1]
:- 如果
X
的元素更小,则排除X
的前i
个元素,递归查找剩余部分的第k-i
小元素。 - 否则排除
Y
的前j
个元素,递归查找剩余部分的第k-j
小元素。
- 如果
- 计算要比较的元素位置:
- 参数说明:
find_median
函数- 假设两个数组长度相同(均为
n
)。 - 合并后的中位数为第
n
和第n+1
小元素的平均值。 - 调用两次
find_kth
分别获取这两个元素的值。
- 假设两个数组长度相同(均为
- 输入处理
- 用户可手动输入两个有序数组,或输入
-1
随机生成测试数据。 - 随机生成时,会生成两个长度为
n
(1到10之间)的有序数组,并打印结果。
- 用户可手动输入两个有序数组,或输入
示例说明
假设输入数组:
X = [1, 3, 5]
Y = [2, 4, 6]
执行流程:
find_median
调用find_kth(n=3)
和find_kth(n+1=4)
。find_kth(3)
通过分治排除得到第3小元素为3。find_kth(4)
通过分治排除得到第4小元素为4。- 中位数为 (3+4)/2=3.5。
算法优势
- 时间复杂度:每次递归排除约一半元素,复杂度为 O(logn)。
- 空间复杂度:递归栈深度为 O(logn)。
- 无需合并数组:避免了 O(n) 的额外空间开销。
注意事项
- 输入数组需预先排序。
- 代码假设两个数组长度相同,若处理不同长度数组需调整
find_median
的参数。 - 随机生成的数据范围为1到99,可修改
random.sample(range(1, 100), n)
调整范围。
代码对比(与C++版本差异)
- 参数传递:Python通过起始索引(
x_start
,y_start
)和长度(x_len
,y_len
)传递子数组,而C++通过指针偏移(如X+i
)直接操作数组。 - 随机生成逻辑:Python使用
random.sample
和sorted
生成有序数组,C++通过循环和手动排序实现。 - 输入处理:Python通过
input().split()
读取数组,C++通过循环和cin
读取。
这段代码是解决两个有序数组中位数问题的经典分治算法实现,高效且易于理解。