У меня есть проблема, и решение ОК-иш. Я надеюсь, что есть лучшее решение.
Проблема
У меня есть массив с около 200 000 целых чисел. Учитывая два индекса, i1 и i2, мне нужно вычислить сумму всех элементов между i1 и i2. Каждое целое число в массиве составляет от 1 до 4 включительно. Например:
a = [1, 3, 2, 4, 3, 2, 4, 1];
subsection_sum(a, 0, 3); // returns 6: (1 + 3 + 2)
Эта операция будет выполнена около 200 000 раз, поэтому должна быть довольно быстрой. Простой счетчик в цикле for - это O (n), и он слишком медленный. Массив никогда не изменяется после построения, поэтому нормально иметь относительно дорогую стадию предварительной обработки.
Мое лучшее решение на данный момент
Этот алгоритм работает за O (log n):
Сначала добавьте в исходный массив нули, пока его длина не станет степенью двойки. Затем разделите массив на две равные части и сохраните сумму каждой. Затем разбейте массив на четверти и сохраните сумму каждого. Затем восьмые. Продолжайте делать это, пока массив не разделится на секции длиной 2 элемента. Для вышеприведенного массива из 8 элементов это выполняется в два этапа:
halves = [(a[0] + a[1] + a[2] + a[3]), (a[4] + a[5] + a[6] + a[7])]
quarters = [(a[0] + a[1]), (a[2] + a[3]), (a[4] + a[5]), (a[6] + a[7])]
Тогда с учетом двух индексов теперь можно вырабатывать сумму subsection_sum за O (log n). Например, subsection_sum (a, 2, 7) == четверти [1] + половинки [1].