Trên kích thước cửa sổ nhỏ hơn, n log n
sắp xếp có thể hoạt động. Có thuật toán nào tốt hơn để đạt được điều này?
Trên kích thước cửa sổ nhỏ hơn, n log n
sắp xếp có thể hoạt động. Có thuật toán nào tốt hơn để đạt được điều này?
Câu trả lời:
Đó là hình thức xấu để sắp xếp một mảng để tính toán trung vị. Các trung vị (và các lượng tử khác) thường được tính toán bằng thuật toán quickselect , với độ phức tạp .
Bạn cũng có thể muốn xem câu trả lời của tôi cho một câu hỏi liên quan gần đây ở đây .
Đây là một bài viết mô tả một thuật toán có thể. Mã nguồn bao gồm và một ứng dụng khá nghiêm trọng (phát hiện sóng hấp dẫn dựa trên giao thoa kế laser), vì vậy bạn có thể mong đợi nó sẽ được kiểm tra tốt.
Nếu bạn sẵn sàng chịu đựng một xấp xỉ, có những phương pháp khác. Ví dụ: một xấp xỉ là một giá trị có thứ hạng nằm trong khoảng cách (do người dùng chỉ định) so với trung bình thực. Ví dụ: trung vị có thứ hạng (bình thường hóa) xếp hạng 0,5 và nếu bạn chỉ định một thuật ngữ lỗi là 10%, bạn muốn có một câu trả lời có thứ hạng từ 0,45 đến 0,55.
Nếu một câu trả lời như vậy là phù hợp, thì có nhiều giải pháp có thể hoạt động trên các cửa sổ trượt dữ liệu. Ý tưởng cơ bản là duy trì một mẫu dữ liệu có kích thước nhất định (khoảng 1 / thuật ngữ lỗi) và tính toán trung vị trên mẫu này. Có thể chỉ ra rằng với xác suất cao, bất kể tính chất của đầu vào, trung vị kết quả đáp ứng các tính chất tôi đã đề cập ở trên.
Vì vậy, câu hỏi chính là làm thế nào để duy trì một mẫu dữ liệu đang chạy ở một kích thước nhất định và có nhiều cách tiếp cận cho điều đó, bao gồm cả kỹ thuật được gọi là lấy mẫu hồ chứa. Ví dụ: bài viết này: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.7136
Nếu bạn duy trì cửa sổ dữ liệu có độ dài k dưới dạng danh sách liên kết đôi được sắp xếp sau đó, bằng phương pháp tìm kiếm nhị phân (để chèn từng phần tử mới khi nó được chuyển vào cửa sổ) và một mảng con trỏ tròn (để xác định ngay các phần tử cần phải xóa), mỗi ca làm việc của cửa sổ đòi hỏi nỗ lực O (log (k)) để chèn một phần tử, chỉ nỗ lực O (1) để xóa phần tử được dịch chuyển ra khỏi cửa sổ và chỉ nỗ lực tìm O (1) trung vị (vì mỗi khi một phần tử được chèn hoặc xóa vào danh sách, bạn có thể cập nhật một con trỏ thành trung vị trong thời gian O (1)). Do đó, toàn bộ nỗ lực xử lý một mảng có độ dài N là O ((nk) log (k)) <= O (n log (k)). Điều này tốt hơn bất kỳ phương pháp nào khác được đề xuất cho đến nay và nó không phải là một xấp xỉ, nó là chính xác.
Như bạn đã đề cập sắp xếp sẽ O(n·log n)
dành cho một cửa sổ có chiều dài n
. Làm điều này di chuyển thêm một l=vectorlength
làm cho tổng chi phí O(l·n·log n)
.
Cách đơn giản nhất để thúc đẩy điều này là bằng cách giữ một danh sách có thứ tự của n phần tử cuối cùng trong bộ nhớ khi di chuyển từ cửa sổ này sang cửa sổ tiếp theo. Khi loại bỏ / chèn một phần tử từ / vào danh sách theo thứ tự, cả hai O(n)
điều này sẽ dẫn đến chi phí O(l·n)
.
Mã giả:
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)
Đây là giải pháp O (1) để tìm trung vị hiện tại và O (log n) để thêm số mới http://www.dsalgo.com/RastyMedian.php
Nếu bạn có thể sống với ước tính thay vì trung bình thực, Thuật toán Remedian (PDF) là một lượt với yêu cầu lưu trữ thấp và độ chính xác được xác định rõ.
Người sửa chữa với cơ sở b tiến hành bằng cách tính toán trung vị của các nhóm quan sát b, và sau đó là trung vị của các trung vị này, cho đến khi chỉ còn một ước tính duy nhất. Phương pháp này chỉ cần k mảng có kích thước b (trong đó n = b ^ k) ...
Tôi đã sử dụng Thư viện C ++ RunningStats này trong một ứng dụng nhúng. Đây là thư viện thống kê chạy đơn giản nhất mà tôi đã tìm thấy.
Từ liên kết:
Mã này là một phần mở rộng của phương pháp Knuth và Welford để tính toán độ lệch chuẩn trong một lần truyền dữ liệu. Nó cũng tính toán độ lệch và kurtosis với giao diện tương tự. Ngoài việc chỉ yêu cầu một lần chuyển qua dữ liệu, thuật toán còn ổn định và chính xác về mặt số.