Ви можете зробити все це в очікуваний амортизований час . Основна хитрість полягає в тому, що нам не потрібна повна потужність черги пріоритету, оскільки частота ключів змінюється лише на 1 під час кожного вставки або видалення.O(1)
Моє рішення нижче - це лише ваше рішення з "неефективною" чергою пріоритетів, яка, як правило, спрацьовує в цьому випадку: максимум черги пріоритетів, реалізований як подвійно пов'язані списки відро ключів, має O (1) insertMin, deleteMax, removeFromBucket та збільшення Ключ.
Підтримуйте подвійно пов'язаний список Buckets, де кожен Bucket має не порожній хеш-набір ключів (який я буду називати когортою) та додатне ціле число (що я буду називати ValCount). У Bucket b кожен ключ k у когорті b має однакову кількість унікальних значень, пов'язаних з ним, у наборі, який ви підтримуєте. Наприклад, якщо у вашому наборі є пари (a, яблуко), (a, авокадо), (b, банан), (c, огірок), (d, плід дракона), де однією буквою є ключі, а плоди - Значення, тоді у вас було б два відра: Одне відро матиме ValCount 2 та когорту, що складається лише з одного ключа: a. Інший відро матиме ValCount 1 та когорту, що складається з трьох клавіш b, c та d.
Подвійно пов'язаний список Bucket повинен вестись упорядкованим ValCount. Важливо, що ми зможемо знайти голову та хвіст списку в час і що ми можемо сплести в новому відрі в O ( 1 ) час, якщо знаємо його сусідів. Немислено я назву список Buckets BucketList.O(1)O(1)
На додаток до BucketList нам знадобиться SetMap, який є ключами хеш-карти зіставленням у ValueBuckets. ValueBucket - це пара, що складається з ValueSet (не порожній хеш-набір значень) та ненульовий вказівник на Bucket. ValueSet, пов'язаний з ключем k, містить усі унікальні значення, пов'язані з k. Вказівник Bucket, пов'язаний із ValueSet, має когорту, рівну розміру ValueSet. Bucket, асоційований з ключем k у SetMap, також асоціюється з ключем k у BucketList.
В C ++:
struct Bucket {
unsigned ValCount;
unordered_set<Key> Cohort;
Bucket * heavier;
Bucket * lighter;
};
Bucket * BucketListHead;
Bucket * BucketListTail;
struct ValueBucket {
unordered_set<Value> ValueSet;
Bucket * bucket;
};
unordered_map<Key, ValueBucket> SetMap;
Щоб знайти максимум частоти пари ключ-значення, нам просто потрібно подивитися на голову BucketList, знайти ключ у когорті, знайти цей ключ у SetMap та знайти значення у ValueSet його ValueBucket. (феу!)
Вставлення та видалення пар ключ-значення складніше.
Щоб вставити або видалити пару ключів-значень, спочатку вставляємо або видаляємо її у SetMap Це змінить розмір ValueSet, тому нам потрібно змінити Bucket, пов'язаний з ключем. Єдині відра, на які нам потрібно буде звернути увагу, щоб внести цю зміну, - це безпосередні сусіди Ковша, ключовим для якого був. У цьому випадку є декілька випадків, і вони, мабуть, не варто в повному обсязі викладати, хоча я буду радий уточнити, якщо у вас все ще виникають проблеми.