Вот решение, которое требует сортировки высоты здания (я собираюсь предположить, от самой низкой до самой высокой). Если данные уже отсортированы, то они должны выполняться за время O (N).
Пусть k будет высотой всех зданий, поэтому мы хотим найти оптимальное k.
Стоимость корректировки всех этих зданий определяется как:
M = Sum(|k-hj|cj, j from 0 to N).
Теперь, поскольку они отсортированы, мы можем найти индекс i такой, что для всех j <= i, hj <= k и для всех j> i, hj> k.
Это означает, что мы можем переписать наше уравнение стоимости следующим образом:
M = Sum((k-hj)cj, j = 0 to i) + Sum((hj-k)cj, j = i+1 to N).
Теперь мы будем перебирать значения k между самым коротким и самым высоким зданием, пока не найдем здание с наименьшей стоимостью (далее мы увидим, что нам не нужно проверять каждое из них)
Расчет стоимости на каждой итерации - это N операций, поэтому вместо этого мы найдем рекурсивное определение нашей функции стоимости:
M(k+1) = Sum((k+1-hj)cj, j = 0 to p) + Sum((hj-k-1)cj, j = p+1 to N).
Мы можем вычесть термины '1' из сумм, чтобы получить:
M(k+1) = Sum((k-hj)cj, j = 0 to p) + Sum((hj-k)cj, j = p+1 to N) + Sum(cj, j = 0 to p) - Sum(cj, j = p+1 to N).
Теперь p - это новый i, и есть 2 возможных случая: p = i или p = i + 1.
если p = i:
M(k+1) = M(k) + Sum(cj, j = 0 to p) - Sum(cj, j = p+1 to N)
и если p = i + 1
M(k+1) = M(k) + Sum(cj, j = 0 to p) - Sum(cj, j = p+1 to N) + 2(k+1 - h(i+1))c(i+1).
В случае, когда p = i, мы можем фактически найти M (k + m) непосредственно из M (k), потому что на каждой итерации мы добавляем только постоянный член (постоянный в терминах k, то есть), поэтому, если p = я:
M(k+m) = M(k) + m(Sum(cj, j = 0 to p) - Sum(cj, j = p+1 to N)).
Это означает, что наша функция образует прямую линию между итерациями, где i является постоянной величиной. Поскольку нас интересует, когда наша функция переходит от уменьшения к увеличению, это не может произойти в середине всех этих итераций. Это может произойти только при увеличении i (p = i + 1) или на первом шаге после (поскольку линия отличается от линии, ведущей к ней).
Из того, что здесь до сих пор, алгоритм будет выглядеть примерно так:
- Сортировать высоты при необходимости (O (NlogN))
- Инициализируйте ваши 4 суммы (две суммы в M (k) и две дополнительные суммы, введенные в M (k + 1)) (O (N))
итерируйте по своим высотам, как это (O (N)), находя минимальное значение по ходу:
-Увеличить k до высоты следующего самого высокого здания минус единица (используя M (k + m)) и посмотреть, представляет ли это новый минимум
-Увеличить k на единицу, изменив значения i, и посмотреть, соответствует ли это новому минимуму
- Распечатайте ответ.
Здесь возможны некоторые другие оптимизации, о которых я пока не особо задумывался.
Очевидным является не пересчитывать ваши суммы, когда я меняюсь.
Я извиняюсь, если математику трудно читать, я новичок в StackOverflow и не выяснил все возможные форматы.
У меня нет кода для поддержки этого, поэтому я надеюсь, что это достаточно хорошо.