쿼드압축 후 개수 세기

Lv. 2

Solution

export function solution(arr: number[][]): [number, number] {
  const n = arr.length;
  const dy = [0, 1, 0, 1];
  const dx = [0, 0, 1, 1];
 
  function compress(y: number, x: number, size: number): [number, number] {
    if (size === 1) {
      return arr[y][x] ? [0, 1] : [1, 0];
    }
    let [numZeros, numOnes] = [0, 0];
    for (let i = 0; i < 4; i++) {
      const [ny, nx] = [y + (size >> 1) * dy[i], x + (size >> 1) * dx[i]];
      const [numZero, numOne] = compress(ny, nx, size >> 1);
      numZeros += numZero;
      numOnes += numOne;
    }
    return numZeros === 0 ? [0, 1] : numOnes === 0 ? [1, 0] : [numZeros, numOnes];
  }
 
  return compress(0, 0, n);
}
 
/* 누적합을 이용한 풀이 */
class PrefixSum {
  n: number;
  prefixSum: number[][];
 
  constructor(arr: number[][]) {
    this.n = arr.length;
    this.prefixSum = Array.from({ length: this.n + 1 }).map(() => new Array(this.n + 1).fill(0));
    arr.forEach((row, y) => {
      row.forEach((num, x) => {
        this.prefixSum[y + 1][x + 1] =
          num + this.prefixSum[y + 1][x] + this.prefixSum[y][x + 1] - this.prefixSum[y][x];
      });
    });
  }
 
  sum(y: number, x: number, size: number): number {
    return (
      this.prefixSum[y + size][x + size] -
      this.prefixSum[y + size][x] -
      this.prefixSum[y][x + size] +
      this.prefixSum[y][x]
    );
  }
}
 
export function solutionWithPrefixSum(arr: number[][]): [number, number] {
  const n = arr.length;
  const prefixSum = new PrefixSum(arr);
 
  let [numZero, numOne] = [0, 0];
  function compress(y: number, x: number, size: number): void {
    const sum = prefixSum.sum(y, x, size);
    if (sum === 0 || sum === size ** 2) {
      if (sum === 0) {
        numZero += 1;
      } else {
        numOne += 1;
      }
    } else {
      compress(y, x, size >> 1);
      compress(y + (size >> 1), x, size >> 1);
      compress(y, x + (size >> 1), size >> 1);
      compress(y + (size >> 1), x + (size >> 1), size >> 1);
    }
  }
 
  compress(0, 0, n);
 
  return [numZero, numOne];
}