На менших розмірах вікон n log n
сортування може працювати. Чи є кращі алгоритми для цього?
На менших розмірах вікон n log n
сортування може працювати. Чи є кращі алгоритми для цього?
Відповіді:
Погана форма сортування масиву для обчислення медіани. Медіани (та інші кванти), як правило, обчислюються за допомогою алгоритму швидкого вибору з складністю .
Ви також можете подивитися на мою відповідь на нещодавнє пов’язане запитання тут .
Ось стаття з описом одного можливого алгоритму. Вихідний код включав і досить серйозне застосування (гравітаційне виявлення хвиль на основі лазерної інтерферометрії), тому можна очікувати, що він буде добре перевірений.
Якщо ви готові терпіти наближення, є й інші методи. Наприклад, одне наближення - це значення, ранг якого знаходиться в межах деякої (визначеної користувачем) відстані від справжньої медіани. Наприклад, медіана має (нормалізований) ранг 0,5, і якщо ви вкажете термін помилки 10%, ви хочете відповісти, що має ранг від 0,45 до 0,55.
Якщо така відповідь доречна, то існує багато рішень, які можуть працювати на розсувних вікнах даних. Основна ідея полягає у підтримці вибірки даних певного розміру (приблизно 1 / термін помилки) та обчислення медіани на цій вибірці. Можна показати, що з високою ймовірністю, незалежно від характеру введення, отримана медіана задовольняє властивості, про які я згадував вище.
Таким чином, головне питання полягає в тому, як підтримувати робочу вибірку даних певного розміру, і для цього існує безліч підходів, включаючи методику, відому як відбір проб пласта. Наприклад, цей документ: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.7136
Якщо ви підтримуєте вікно даних довжиною k до сортованого подвійно пов'язаного списку, то за допомогою двійкового пошуку (для вставки кожного нового елемента у міру його переміщення у вікно) та кругового масиву покажчиків (негайно знаходити елементи, які потрібно видалити), кожен зсув вікна вимагає зусилля O (log (k)) для вставки одного елемента, лише O (1) зусилля для видалення елемента, зміщеного з вікна, і лише O (1) зусилля для пошуку медіана (оскільки кожен раз, коли один елемент вставляється чи видаляється у списку, ви можете оновити покажчик на медіану за час O (1)). Таким чином, загальне зусилля на обробку масиву довжиною N становить O ((nk) log (k)) <= O (n log (k)). Це краще, ніж будь-який з інших методів, запропонованих до цих пір, і це не наближення, це точно.
Як ви згадали, сортування було б O(n·log n)
для вікна довжини n
. Здійснення цього переміщення додає ще одне, що l=vectorlength
становить загальну вартість O(l·n·log n)
.
Найпростіший спосіб просунути це - зберігати впорядкований список останніх n елементів у пам’яті при переході від одного вікна до наступного. Оскільки обидва видалення / вставлення одного елемента з / у упорядкований список, O(n)
це призведе до витрат O(l·n)
.
Псевдокод:
l = length(input)
aidvector = sort(input(1:n))
output(i) = aid(n/2)
for i = n+1:l
remove input(i-n) from aidvector
sort aid(n) into aidvector
output(i) = aid(n/2)
Ось рішення O (1) для пошуку поточної медіани та O (log n) для додавання нового числа http://www.dsalgo.com/RunningMedian.php
Якщо ви можете жити з оцінкою замість справжньої медіани, алгоритм Ремедіану (PDF) - однопрохідний з низькими вимогами до зберігання та чітко визначеною точністю.
Засіб з базою b протікає шляхом обчислення медіанів груп b спостережень, а потім медіанів цих медіанів, поки не залишиться лише одна оцінка. Цей метод просто потребує k масивів розміру b (де n = b ^ k) ...
Я використав цю бібліотеку RunningStats C ++ у вбудованому додатку. Це найпростіша бібліотека статистичних даних, яку я ще знайшов.
За посиланням:
Код - це розширення методу Кнута і Велфорда для обчислення стандартного відхилення за один прохід через дані. Він також обчислює косисть і куртоз, а також аналогічний інтерфейс. Крім того, що потрібно лише один прохід через дані, алгоритм є чисельно стійким і точним.