Префиксные суммы (Prefix Sums)

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

📝 Определение

Пусть дан массив nums длины . Массив префиксных сумм prefix (обычно длины ) определяется так:

То есть:

  • prefix[0] = 0 (базовый случай, сумма пустого подмассива)
  • prefix[1] = nums[0]
  • prefix[2] = nums[0] + nums[1]
  • prefix[i] = nums[0] + ... + nums[i-1]

Важно: Часто удобно делать prefix на 1 элемент длиннее nums, чтобы prefix[0] был равен 0. Это упрощает формулы (не нужно обрабатывать случай L=0 отдельно).

🚀 Зачем это нужно?

Главное преимущество — быстрое вычисление суммы подмассива (Range Sum Query).

Формула суммы на отрезке

Чтобы найти сумму элементов от индекса до (включительно):

Почему это работает? prefix[R+1] — это сумма nums[0]...nums[R]. prefix[L] — это сумма nums[0]...nums[L-1]. Вычитая из первой суммы вторую, мы “отрезаем” начальную часть, оставляя только nums[L]...nums[R].


💻 Примеры

1. Визуализация

Пусть nums = [3, 1, 4, 2, 5]

Index012345
nums31425-
prefix03481015

Пример вычисления: Сумма подмассива nums[1..3] (элементы 1, 4, 2): Sum(1, 3) = prefix[4] - prefix[1] = Проверка:

2. Реализация на JavaScript

/**
 * @param {number[]} nums
 * @return {number[]}
 */
function buildPrefixSum(nums) {
    const n = nums.length;
    // Создаем массив на 1 больше, заполненный нулями
    const prefix = new Array(n + 1).fill(0);
    
    for (let i = 0; i < n; i++) {
        prefix[i + 1] = prefix[i] + nums[i];
    }
    
    return prefix;
}
 
/**
 * @param {number[]} prefix - Массив префиксных сумм
 * @param {number} left - Начальный индекс
 * @param {number} right - Конечный индекс
 * @return {number}
 */
function getRangeSum(prefix, left, right) {
    return prefix[right + 1] - prefix[left];
}
 
// Использование
const nums = [1, 2, 3, 4, 5];
const P = buildPrefixSum(nums);
console.log(getRangeSum(P, 1, 3)); // 9  (nums[1]+nums[2]+nums[3] = 2+3+4)

⚙️ Сложность

ОперацияВременная сложностьПространственная сложность
Построение (Build)
Запрос (Query)

Практика