작은 창 크기에서는 n log n
정렬이 작동 할 수 있습니다. 이것을 달성하기위한 더 나은 알고리즘이 있습니까?
작은 창 크기에서는 n log n
정렬이 작동 할 수 있습니다. 이것을 달성하기위한 더 나은 알고리즘이 있습니까?
답변:
중앙값을 계산하기 위해 배열을 정렬하는 것은 좋지 않습니다. 중앙값 (및 기타 Quantile)은 일반적으로 복잡도 와 함께 빠른 선택 알고리즘을 사용하여 계산됩니다 .
최근 관련 질문에 대한 답변을 여기에서 확인할 수도 있습니다 .
다음 은 하나의 가능한 알고리즘을 설명하는 기사입니다. 소스 코드가 포함되어 있고 상당히 심각한 응용 프로그램 (레이저 간섭계를 기반으로 한 중력파 감지)을 잘 테스트 할 수 있습니다.
근사치를 용납하려는 경우 다른 방법이 있습니다. 예를 들어 한 근사값은 순위가 실제 중앙값에서 (사용자 지정) 거리 내에있는 값입니다. 예를 들어, 중앙값은 (정규화 된) 순위가 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
실제 중앙값 대신 추정값으로 살 수있는 경우, Remedian Algorithm (PDF) 은 스토리지 요구 사항이 낮고 정확도가 정의 된 원 패스입니다.
기본 b에 대한 교정은 단일 관측치 만 남을 때까지 b 개의 관측치 그룹의 중간 값을 계산 한 다음이 중간 값의 중간 값을 계산하여 진행됩니다. 이 방법은 단지 크기가 b 인 k 개의 배열 만 필요합니다 (n = b ^ k) ...
임베디드 응용 프로그램 에서이 RunningStats C ++ 라이브러리 를 사용했습니다. 내가 찾은 가장 간단한 실행 통계 라이브러리입니다.
링크에서 :
이 코드는 데이터를 한 번에 표준 편차를 계산하기위한 Knuth 및 Welford 방법의 확장입니다. 비슷한 인터페이스를 사용하여 왜도 및 첨도를 계산합니다. 데이터를 한 번만 통과하면되는 알고리즘은 수치 적으로 안정적이고 정확합니다.