Припустимо, що ми читаємо послідовність з n
Як вирішити цю проблему?
Припустимо, що ми читаємо послідовність з n
Як вирішити цю проблему?
Відповіді:
Створіть буфер розміром 2 k . Читайте в 2 K елементів з масиву. Використовуйте алгоритм вибору лінійного часу, щоб розділити буфер, щоб першими були найменші k елементи; це займає час O ( k ) . Тепер прочитайте в буфер ще один k елементів з масиву, замінивши k найбільших елементів у буфері, розділіть буфер, як раніше, і повторіть.
Це займає O ( k ∗ n / k ) = O ( n ) час і O ( k ) простір.
min
Ви можете зробити це в пам'яті O ( k ) та O ( n log k ) , створивши фіксований розмір max-heap з перших k елементів за O ( k ) час, потім повторити і решту масиву та натиснувши новий елемент, а потім вискакує для O ( log k ) для кожного елемента, даючи загальний час O ( k + n log k ) = O ( n log k ) .
Ви можете зробити це в допоміжній пам’яті O ( log n ) та O ( n ) час, використовуючи алгоритм вибору медіани медіанів, вибираючи при k і повертаючи перші k елементи. Без зміни асимптотики ви можете використовувати інтроселект для прискорення середнього випадку. Це канонічний спосіб вирішити вашу проблему.
Зараз технічно O ( log n ) і O ( k ) є незрівнянними. Однак я стверджую, що O ( log n ) є кращим на практиці, оскільки він фактично постійний, враховуючи, що жодна комп'ютерна система не має більше 2 64 байт пам'яті, log 2 64 = 64 . Тим часом k може вирости таким же великим, як n .