K-th Nearest Obstacle Queries - Heap [JS]

Description 

Solution: Heap

Keep a max heap of the kth nearest obstacle distances from the origin.
If the size of the heap exceeds k, we remove the furthest distance.
The top of the max heap is the kth nearest obstacle at any point in time.

n = length of queries
Time Complexity: O(n log(k))
Space Complexity: O(k)

function resultsArray(queries, k) {
  let heap = new Heap((a, b) => b - a);
  let results = [];
  for (let [x, y] of queries) {
    let dist = Math.abs(x) + Math.abs(y);
    heap.add(dist);
    if (heap.size > k) {
      heap.remove();
    }
    results.push(heap.size < k ? -1 : heap.top());
  } 
  return results;
};

class Heap {
  constructor(comparator = ((a, b) => a - b)) {
    this.values = [];
    this.comparator = comparator;
    this.size = 0;
  }
  add(val) {
    this.size++;
    this.values.push(val);
    let idx = this.size - 1, parentIdx = Math.floor((idx - 1) / 2);
    while (parentIdx >= 0 && this.comparator(this.values[parentIdx], this.values[idx]) > 0) {
      [this.values[parentIdx], this.values[idx]] = [this.values[idx], this.values[parentIdx]];
      idx = parentIdx;
      parentIdx = Math.floor((idx - 1) / 2);
    }
  }
  remove() {
    if (this.size === 0) return -1;
    this.size--;
    if (this.size === 0) return this.values.pop();
    let removedVal = this.values[0];
    this.values[0] = this.values.pop();
    let idx = 0;
    while (idx < this.size && idx < Math.floor(this.size / 2)) {
      let leftIdx = idx * 2 + 1, rightIdx = idx * 2 + 2;
      if (rightIdx === this.size) {
        if (this.comparator(this.values[leftIdx], this.values[idx]) > 0) break;
        [this.values[leftIdx], this.values[idx]] = [this.values[idx], this.values[leftIdx]];
        idx = leftIdx;
      } else if (this.comparator(this.values[leftIdx], this.values[idx]) < 0 || this.comparator(this.values[rightIdx], this.values[idx]) < 0) {
        if (this.comparator(this.values[leftIdx], this.values[rightIdx]) <= 0) {
          [this.values[leftIdx], this.values[idx]] = [this.values[idx], this.values[leftIdx]];
          idx = leftIdx;
        } else {
          [this.values[rightIdx], this.values[idx]] = [this.values[idx], this.values[rightIdx]];
          idx = rightIdx;
        }
      } else {
        break;
      }
    }
    return removedVal;
  }
  top() {
    return this.values[0];
  }
  isEmpty() {
    return this.size === 0;
  }
}

Comments

Popular posts from this blog

Beautiful Towers II - Monotonic Increasing Stack [JS]

Minimum Number of Operations to Sort a Binary Tree by Level - BFS & Cycle Counting Explained [JS]

Maximum Sum of Distinct Subarrays With Length K - Sliding Window w/ Two Pointers & Set [JS]

Maximum Score After Applying Operations on a Tree - DFS [JS]

Divide Nodes Into the Maximum Number of Groups - Union Find & BFS [JS]