예상 상각 시간 에이 모든 작업을 수행 할 수 있습니다 . 중요한 트릭은 각 삽입 또는 삭제 중에 키 빈도가 1 씩만 변경되므로 우선 순위 큐의 모든 기능이 필요하지 않다는 것입니다.O(1)
아래의 내 솔루션은 실제로이 경우에 효과가있는 "비효율적"우선 순위 대기열이있는 솔루션입니다. 이중으로 연결된 키 버킷 목록으로 구현 된 최대 우선 순위 대기열에는 O (1) insertMin, deleteMax, removeFromBucket 및 증가 키.
이중으로 연결된 버킷 목록을 유지합니다. 각 버킷에는 비어 있지 않은 해시 키 집합 (코호트라고 함)과 양의 정수 (ValCount라고 함)가 있습니다. 버킷 b에서 b의 코호트에있는 각 키 k는 유지 관리중인 세트에서 동일한 수의 고유 값을 갖습니다. 예를 들어, 세트에 (a, apple), (a, avocado), (b, banana), (c, cucumber), (d, dragon fruit) 쌍이 있으면 단일 문자가 키이고 과일이있는 경우 값은 두 개의 버킷이 있습니다. 하나의 버킷은 ValCount가 2이고 코호트는 하나의 키로 만 구성됩니다. 다른 버킷의 ValCount는 1이고 코호트는 3 개의 키 b, c 및 d로 구성됩니다.
이중 연결 버킷 목록은 ValCount에서 주문해야합니다. 시간에 목록의 머리와 꼬리를 찾을 수 있고 이웃을 알면 O ( 1 ) 시간 에 새로운 버킷을 스플 라이스 할 수 있어야합니다. 상상도 못하게 버킷 목록을 BucketList라고합니다.O(1)O(1)
BucketList 외에도 ValueBuckets에 키를 매핑하는 해시 맵인 SetMap이 필요합니다. ValueBucket은 ValueSet (빈 값이 아닌 해시 값 집합)과 버킷에 대한 널이 아닌 포인터로 구성된 쌍입니다. 키 k와 연관된 ValueSet에는 k와 관련된 모든 고유 값이 포함됩니다. ValueSet과 연관된 Bucket 포인터는 ValueSet의 크기와 동일한 코호트를 갖습니다. SetMap에서 키 k와 연관된 Bucket도 BucketList의 키 k와 연관됩니다.
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에서 해당 키를 찾은 다음 ValueBucket의 ValueSet에서 값을 찾으면됩니다. (퓨!)
키-값 쌍을 삽입하고 삭제하는 것이 더 까다 롭습니다.
키-값 쌍을 삽입하거나 삭제하려면 먼저 SetMap에 삽입하거나 삭제합니다. 그러면 ValueSet의 크기가 변경되므로 키와 관련된 버킷을 수정해야합니다. 이 변경 사항을 확인하기 위해 살펴볼 버킷은 버킷의 바로 옆에있을 것입니다. 여기에는 몇 가지 사례가 있으며 아마 기뻐할 것입니다. 여전히 문제가있는 경우 자세히 설명합니다.