Number of Atoms

HardHash TableStringStackSorting

Solution

export function countOfAtoms(formula: string): string {
  function addDigit(num: number, digit: string) {
    if (num === 0) {
      return parseInt(digit);
    }
    return parseInt(`${digit}${num}`);
  }
 
  const n = formula.length;
  const stack: number[] = [];
  const counter = new Counter<string>();
 
  let element = '';
  let elementCount = 0;
  let coefficient = 1;
  for (let i = n - 1; 0 <= i; i--) {
    const char = formula[i];
 
    if (/[0-9]/.test(char)) {
      elementCount = addDigit(elementCount, char);
    } else if (/[A-Z]/.test(char)) {
      element = `${char}${element}`;
      counter.update(element, Math.max(1, elementCount) * coefficient);
      element = '';
      elementCount = 0;
    } else if (/[a-z]/.test(char)) {
      element = `${char}${element}`;
    } else if (char === ')') {
      if (0 < elementCount) {
        stack.push(elementCount);
        coefficient *= elementCount;
      } else {
        stack.push(1);
      }
      elementCount = 0;
    } else if (char === '(') {
      coefficient = Math.floor(coefficient / stack.pop()!);
      elementCount = 0;
    }
  }
  const elements = [...counter.entries()].sort(([a], [b]) => (a < b ? -1 : 1));
  return elements.map(([element, count]) => (1 < count ? `${element}${count}` : element)).join('');
}
 
class Counter<K> extends Map<K, number> {
  constructor(entries?: K[]) {
    super();
    entries?.forEach((entry) => {
      this.add(entry);
    });
  }
  get(key: K): number {
    return super.get(key) ?? 0;
  }
 
  update(key: K, value: number) {
    super.set(key, this.get(key) + value);
  }
 
  add(key: K): void {
    super.set(key, this.get(key) + 1);
  }
 
  sub(key: K): void {
    super.set(key, this.get(key) - 1);
  }
}

Complexity

  • Time: O(N)
  • Space: O(N)