Sobes.tech
Middle — Senior
30

Как обрабатывать поток данных для подсчёта медианы с ограниченной памятью?

Companies where asked
Ниармедик Ваш Доктор Рядом

Answer from AI

sobes.tech AI

Для подсчёта медианы в потоке данных с ограниченной памятью используют алгоритмы, которые не требуют хранения всех элементов. Один из популярных подходов — поддерживать две структуры данных (например, два кучи):

  • Максимальная куча для нижней половины элементов
  • Минимальная куча для верхней половины элементов

При поступлении нового числа его добавляют в одну из куч, затем балансируют размеры куч так, чтобы их размеры отличались не более чем на 1. Медиана при этом — это либо корень максимальной кучи (если она больше), либо среднее корней обеих куч.

Такой метод позволяет получать медиану за O(log n) на каждый элемент и использовать память пропорционально количеству элементов, но без хранения всего потока.

Пример на Python:

import heapq

class MedianFinder:
    def __init__(self):
        self.low = []  # max heap (invert values)
        self.high = [] # min heap

    def add_num(self, num):
        heapq.heappush(self.low, -num)
        # Переместить максимум из low в high
        if self.low and self.high and (-self.low[0]) > self.high[0]:
            val = -heapq.heappop(self.low)
            heapq.heappush(self.high, val)

        # Балансировка размеров
        if len(self.low) > len(self.high) + 1:
            val = -heapq.heappop(self.low)
            heapq.heappush(self.high, val)
        elif len(self.high) > len(self.low):
            val = heapq.heappop(self.high)
            heapq.heappush(self.low, -val)

    def find_median(self):
        if len(self.low) > len(self.high):
            return float(-self.low[0])
        else:
            return (-self.low[0] + self.high[0]) / 2

# Использование:
finder = MedianFinder()
for num in [5, 15, 1, 3]:
    finder.add_num(num)
    print(finder.find_median())

Этот подход эффективен для потоковой обработки с ограниченной памятью.