Предположим, мы получаем цифры в потоке. После получения каждого числа необходимо вычислить взвешенную сумму последних чисел, где веса всегда одинаковы, но произвольны.
Насколько эффективно это можно сделать, если нам разрешено сохранять структуру данных, чтобы помочь с вычислениями? Можем ли мы сделать что-то лучше, чем , то есть пересчитывать сумму при каждом получении числа?
Например: Предположим , что веса . В какой -то момент мы имеем список последних чисел , а взвешенная сумма .
Когда другой номер, , получена, мы обновить список , чтобы получить и нам нужно вычислить .
Рассмотрение использования БПФ . Особый случай этой проблемы, по-видимому, эффективно решается с помощью быстрого преобразования Фурье. Здесь мы вычислим взвешенные суммы в упаковке N . Другими словами, мы получаем N чисел, и только тогда мы можем вычислить соответствующие N взвешенных сумм. Для этого нам нужно N - 1 прошлых чисел (для которых суммы уже были вычислены) и N новых чисел, всего 2 N - 1 чисел.
Если этот вектор входных чисел и весовой вектор определяют коэффициенты многочленов P ( x ) и Q ( x ) с обратными коэффициентами в Q , мы видим, что произведение P ( x ) × Q ( x ) является полиномом чьи коэффициенты перед x N - 1 до x 2 N - 2 - это именно те взвешенные суммы, которые мы ищем. Они могут быть вычислены с использованием БПФ в Θ ( N ∗ log времени, что дает нам в среднем thetas ; ( журнала ( N ) ) раз в номер входа.
Это, однако, не является решением проблемы, как указано, потому что требуется, чтобы взвешенная сумма вычислялась эффективно каждый раз, когда принимается новое число - мы не можем задержать вычисление.
источник
Ответы:
Вот разработка вашего подхода. Каждые итераций мы используем алгоритм FFT для вычисления m значений свертки за время O ( n log n ) , предполагая, что последующие m значений равны нулю. Другими словами, мы вычисляем n - 1 ∑ i = 0 w i a t - i + k ,м м O ( n logн ) м
где w i - это n весов (или обратных весов), a i - входная последовательность, t - текущее время и a t ′ = 0 для t ′ > t .
Для каждой из следующих итераций мы можем рассчитать требуемую свертку за время O ( m ) (для i- й итерации требуется время O ( i ) ). Таким образом, амортизированное время составляет O ( m ) + O ( n log n / m ) . Это минимизируется путем выбора m = √м O ( м ) я O ( я ) O ( m ) + O ( n logн / м ) , который дает амортизированное время работыO( √m = n logN-----√ .O ( n logN-----√)
Мы можем улучшить это до наихудшего времени работы , разбив вычисление на части. Зафиксируемmи определим b T , p , o = m - 1 ∑ i = 0 w p m + i a T m - i + o ,O ( n logN-----√) м
Каждый C T , p зависит только от 2 м входов, поэтому его можно вычислить за время O ( m log m ) . Кроме того, учитывая C ⌊ t / m ⌋ - p , p для 0 ≤ p ≤ n
источник