Design a Number Container System

MediumHash TableDesignHeap (Priority Queue)Ordered Set

Solution

  1. container는 현재 indexnum을 저장
  2. heaps는 현재 num을 가지고 있는 indexHeap을 저장
    • Heap을 통해, 현재 num을 가지고 있는 가장 작은 인덱스를 검색
    • change를 할 때 마다, 해당 Heap을 정리하지 않고, find를 할 때, 현재 container에서 indexnum을 가지고 있는지를 통해 정리

change

  1. container에 주어진 indexnum을 반영
  2. 이전에 index가 다른 num을 가지고 있는 경우, 해당 numHeap의 가장 작은 인덱스가 주어진 index라면, 해당 index 삭제

find

  1. heaps를 통해, 주어진 num을 가지고 있는 index들을 저장하고 있는 Heap을 검색
  2. Heap이 없는 경우, -1을 반환
  3. Heap을 순환하면서, containerindex가 가지고 있는 num과 일치하는 경우, 해당 index를 반환
  4. 일치하지 않는 경우는, Heap에서 삭제
import { Heap } from '@algorithm/lib';
 
export class NumberContainers {
  private readonly container: Map<number, number>;
  private readonly heaps: Map<number, Heap<number>>;
  constructor() {
    this.container = new Map();
    this.heaps = new Map();
  }
 
  private getHeap(num: number): Heap<number> {
    const heap = this.heaps.get(num);
    if (heap !== undefined) {
      return heap;
    }
    const newHeap = new Heap<number>((a, b) => a - b);
    this.heaps.set(num, newHeap);
    return newHeap;
  }
 
  change(index: number, num: number): void {
    const prevNum = this.container.get(index);
    if (prevNum !== undefined && this.heaps.has(prevNum)) {
      const prevHeap = this.getHeap(prevNum);
      if (prevHeap.peek === index) {
        prevHeap.pop();
      }
    }
    const pq = this.getHeap(num);
    pq.push(index);
    this.container.set(index, num);
  }
 
  find(num: number) {
    if (!this.heaps.has(num)) {
      return -1;
    }
 
    const heap = this.getHeap(num);
    while (!heap.isEmpty) {
      if (heap.peek !== undefined && this.container.get(heap.peek) === num) {
        return heap.peek;
      }
      heap.pop();
    }
    return -1;
  }
}

Complexity

  • Time: O(log2n)O(\log_2 n)
  • Space: O(n)O(n)