Construct Target Array With Multiple Sums

HardArrayHeap (Priority Queue)

Solution

type Comparator<T> = (a: T, b: T) => number;
 
class Heap<T> {
  heap: T[];
  comparator: Comparator<T>;
 
  constructor(comparator: Comparator<T>) {
    this.heap = [];
    this.comparator = comparator;
  }
 
  get length() {
    return this.heap.length;
  }
 
  get peek(): T | undefined {
    return this.heap[0];
  }
 
  get isEmpty() {
    return this.length === 0;
  }
 
  private swap(index1: number, index2: number): void {
    [this.heap[index1], this.heap[index2]] = [this.heap[index2], this.heap[index1]];
  }
 
  private parentIndex(index: number): number {
    return (index - 1) >> 1;
  }
 
  private leftIndex(index: number): number {
    return (index << 1) + 1;
  }
 
  private rightIndex(index: number): number {
    return (index << 1) + 2;
  }
 
  private compare(index1: number, index2: number) {
    return this.comparator(this.heap[index1], this.heap[index2]);
  }
 
  private canShift(index1: number, index2: number): boolean {
    return 0 < this.compare(index1, index2);
  }
 
  private shiftDown(): void {
    let currentIndex = 0;
    while (this.leftIndex(currentIndex) < this.length) {
      const leftIndex = this.leftIndex(currentIndex);
      const rightIndex = this.rightIndex(currentIndex);
      const childIndex =
        rightIndex < this.length && this.compare(rightIndex, leftIndex) < 0
          ? rightIndex
          : leftIndex;
      if (!this.canShift(currentIndex, childIndex)) {
        return;
      }
      this.swap(currentIndex, childIndex);
      currentIndex = childIndex;
    }
  }
 
  private shiftUp(): void {
    let currentIndex = this.length - 1;
    while (0 < currentIndex) {
      const parentIndex = this.parentIndex(currentIndex);
      if (!this.canShift(parentIndex, currentIndex)) {
        return;
      }
      this.swap(currentIndex, parentIndex);
      currentIndex = parentIndex;
    }
  }
 
  push(item: T): void {
    this.heap.push(item);
    this.shiftUp();
  }
 
  pop(): T | undefined {
    if (this.length <= 1) {
      return this.heap.pop();
    }
    const result = this.peek;
    this.swap(0, this.length - 1);
    this.heap.pop();
    this.shiftDown();
    return result;
  }
}
 
export function isPossible(target: number[]): boolean {
  const heap = new Heap<number>((a, b) => b - a);
  target.forEach((value) => heap.push(value));
 
  let totalValue = target.reduce((a, b) => a + b, 0);
 
  while (heap.peek !== 1) {
    const currentValue = heap.pop();
    if (currentValue === undefined) {
      return false;
    }
    totalValue -= currentValue;
    if (currentValue <= totalValue || totalValue < 1) {
      return false;
    }
    const prevValue = currentValue % totalValue;
    totalValue += prevValue;
    heap.push(prevValue || totalValue);
  }
  return true;
}