[Introducción a algoritmos y estructuras de datos] Encuentre la mediana de dos matrices ordenadas (requiere O (log (n + m))

Resolver usando dicotomía

  • Paso 1, k = (n + m) / 2
    Después de fusionar las dos matrices, tome la mediana
    - si n + m es par, tome la más pequeña K, K + 1
    - si n + m es impar, tome la primera K pequeño número
  • Paso 2, compare los números K /
    2 de las dos matrices y redondee hacia abajo. Si el número en num1 es menor que el número en num2, elimine los primeros números K / 2 en num1
  • Paso 3: Actualice el valor de K. En las nuevas matrices num1 y num2, continúe eliminando los primeros números K / 2.
    Inserte la descripción de la imagen aquí
    Utilice el método de dicotomía para resolver.
    Si una de las matrices está vacía, seleccione el resto de otra matriz.
    Si K = 1, Luego, de las dos matrices, encuentre la más pequeña
    nums1 = [1, 3, 5, 7]
    nums2 = [1,2,3,4,5,6,7,8,9,10]
    porque n + m es par, mediana = (7º más pequeño + 8º más pequeño) / 2

Inserte la descripción de la imagen aquí

"""
    寻找两个有序数组的中位数
    利用二分查找的优势,求解
"""

# 在nums1[start1,end1], nums2[start2, end2]两个数组中,找第k小的数
def get_kth_num(nums1, start1, end1, nums2, start2, end2, k):
    len1 = end1 - start1 + 1  # 第一个数组的长度
    len2 = end2 - start2 + 1 # 第二个数组的长度

    # 让 len1 的长度小于 len2,这样就能保证如果有数组空了,一定是 len1 
    if len1 > len2:  # 这里想要保住len1的长度比len2的长度小,如果len1长,则把len1和len2颠倒下
        return get_kth_num(nums2, start2, end2, nums1, start1, end1, k)
    if len1 == 0:  # 此时len2(那个数比较多的数组)还是有值,但是len1已经空了
        return nums2[start2 + k - 1]

    if k == 1: 
        return min(nums1[start1], nums2[start2])  # 用一个min函数找两者中较小的那个

    # 两个数组,分别前进k/2个数
    i = int(start1 + min(len1, k / 2) - 1)
    j = int(start2 + min(len2, k / 2) - 1)

    if nums1[i] < nums2[j]:
        # 第一个数组,前k/2去掉,在剩余的数组中,继续查找
        return get_kth_num(nums1, i + 1, end1, nums2, start2, end2, k - (i - start1 + 1))
    else:
        # 第二个数组,前k/2去掉,在剩余的数组中,继续查找
        return get_kth_num(nums1, start1, end1, nums2, j + 1, end2, k - (j - start2 + 1))

# 外层函数:找两个有序数组中的中位数
def find_median(nums1, nums2):
    n = len(nums1)
    m = len(nums2)
    # 第一个中位数
    left = int((n + m + 1) / 2)
    # 第二个中位数
    right = int((n + m + 2) / 2)
#  以下分支结构实现两个数组奇数个找出来,偶数个找出两个数再取平均数
    if left == right:
        result = get_kth_num(nums1, 0, n - 1, nums2, 0, m - 1, left)    
    else:
        result = (get_kth_num(nums1, 0, n - 1, nums2, 0, m - 1, left) + get_kth_num(nums1, 0, n - 1, nums2, 0, m - 1, right)) / 2
    return result

"""
nums1 = [1, 2, 3]
nums2 = [4, 5]
"""
nums1 = [1, 3, 5, 7]
nums2 = [1,2,3,4,5,6,7,8,9,10]

print (find_median(nums1, nums2))
    

Publicado 42 artículos originales · elogiado 28 · visitas 4961

Supongo que te gusta

Origin blog.csdn.net/KaelCui/article/details/105286771
Recomendado
Clasificación