Эффективные алгоритмы «разделяй и властвуй» для поиска k-го наименьшего элемента в массиве

В этой статье мы рассмотрим различные эффективные алгоритмы «разделяй и властвуй» для поиска k-го наименьшего элемента в массиве. Мы предоставим пошаговые объяснения вместе с примерами кода для каждого алгоритма, что позволит вам понять и реализовать их в своих собственных проектах. Используя подход «разделяй и властвуй», эти алгоритмы обеспечивают более низкую временную сложность по сравнению с традиционными методами, такими как сортировка всего массива. Давайте погрузимся!

Метод 1: алгоритм быстрого выбора
Алгоритм быстрого выбора представляет собой эффективный подход «разделяй и властвуй» для поиска k-го наименьшего элемента. Это вариант алгоритма быстрой сортировки, который работает путем разделения массива вокруг опорного элемента. Основная идея состоит в том, чтобы повторно разбить массив до тех пор, пока сводный элемент не окажется в своей окончательной отсортированной позиции, а затем рекурсивно применить алгоритм к левому или правому разделу в зависимости от значения k.

def quick_select(arr, left, right, k):
    if left == right:
        return arr[left]
    pivot_index = partition(arr, left, right)
    if k == pivot_index:
        return arr[k]
    elif k < pivot_index:
        return quick_select(arr, left, pivot_index - 1, k)
    else:
        return quick_select(arr, pivot_index + 1, right, k)
def partition(arr, left, right):
    pivot = arr[right]
    i = left - 1
    for j in range(left, right):
        if arr[j] <= pivot:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    arr[i + 1], arr[right] = arr[right], arr[i + 1]
    return i + 1

Метод 2: Алгоритм медианы медиан
Алгоритм медианы медиан — это еще один подход «разделяй и властвуй», который улучшает производительность алгоритма QuickSelect в наихудшем случае. Он делит массив на более мелкие подгруппы, находит медиану каждой подгруппы и рекурсивно применяет алгоритм для поиска медианы медиан. Эта медиана медиан затем используется в качестве основы для разделения.

def median_of_medians(arr, left, right, k):
    if left == right:
        return arr[left]
    pivot = find_pivot(arr, left, right)
    pivot_index = partition(arr, left, right, pivot)
    if k == pivot_index:
        return arr[k]
    elif k < pivot_index:
        return median_of_medians(arr, left, pivot_index - 1, k)
    else:
        return median_of_medians(arr, pivot_index + 1, right, k)
def find_pivot(arr, left, right):
    # Divide the array into subgroups of size 5
    subgroups = [arr[i:i+5] for i in range(left, right + 1, 5)]
    # Find the median of each subgroup
    medians = [sorted(subgroup)[len(subgroup)//2] for subgroup in subgroups]
    # Recursively find the median of medians
    if len(medians) <= 5:
        return sorted(medians)[len(medians)//2]
    else:
        return median_of_medians(medians, 0, len(medians) - 1, len(medians)//2)
def partition(arr, left, right, pivot):
    pivot_index = arr.index(pivot)
    arr[pivot_index], arr[right] = arr[right], arr[pivot_index]
    i = left - 1
    for j in range(left, right):
        if arr[j] <= pivot:
            i += 1
            arr[i], arr[j] = arr[j], arr[i]
    arr[i + 1], arr[right] = arr[right], arr[i + 1]
    return i + 1

Метод 3: алгоритм на основе сортировки слиянием
Алгоритм на основе сортировки слиянием — это еще один подход «разделяй и властвуй», который находит k-й наименьший элемент путем рекурсивного деления массива на более мелкие подмассивы до тех пор, пока не будет достигнут базовый случай. Он использует концепцию объединения двух отсортированных массивов для эффективного поиска k-го элемента.

def merge_sort(arr):
    if len(arr) <= 1:
        return arr
    mid = len(arr) // 2
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])
    return merge(left, right)
def merge(left, right):
    result = []
    i, j = 0, 0
    while i < len(left) and j < len(right):
        if left[i] <= right[j]:
            result.append(left[i])
            i += 1
        else:
            result.append(right[j])
            j += 1
    result.extend(left[i:])
    result.extend(right[j:])
    return result
def kth_smallest_merge_sort(arr, k):
    sorted_arr = merge_sort(arr)
    return sorted_arr[k - 1]

В этой статье мы рассмотрели три эффективных алгоритма «разделяй и властвуй» для поиска k-го наименьшего элемента в массиве. Алгоритм QuickSelect, алгоритм Median of Medians и алгоритм на основе MergeSort предоставляют эффективные решения с различными компромиссами. Используя эти алгоритмы, вы можете значительно сократить временные затраты по сравнению с традиционными подходами к сортировке. Мы предоставили подробные примеры кода для каждого алгоритма, чтобы помочь вам реализовать их в своих проектах. Приятного кодирования!