알고리즘
[Javascript] 프로그래머스 - 쿼드압축 후 개수 세기
J3SUNG
2025. 2. 5. 06:49
728x90
문제 설명
0과 1로 이루어진 2^n x 2^n 크기의 2차원 정수 배열 arr이 주어집니다. 이 배열을 쿼드 트리와 같은 방식으로 압축하려 합니다.
압축 방식은 다음과 같습니다:
- 특정 영역 S를 선택합니다.
- S 내 모든 값이 같다면, 하나의 값으로 압축합니다.
- 값이 다르면 S를 4개의 균일한 정사각형 영역으로 나누고, 각 영역에 대해 같은 방식으로 압축을 시도합니다.
- 최종적으로 압축이 완료된 후, 배열에 남아있는 0의 개수와 1의 개수를 반환합니다.
제한 사항
- arr의 크기는 1 이상 1024 이하이며, 2의 거듭 제곱수 형태입니다. (예: 1, 2, 4, 8, ..., 1024)
- arr는 정사각형 배열입니다.
- arr의 모든 요소는 0 또는 1입니다.
해결 방법
알고리즘: 분할 정복
- 주어진 배열의 특정 영역 (sy, sx) ~ (ey, ex)가 모두 같은 값인지 확인합니다.
- 만약 같은 값이라면 해당 숫자의 개수를 반환합니다.
- 그렇지 않다면, 영역을 4개로 나누고 재귀적으로 같은 과정을 수행합니다.
- 4개의 영역에서 반환된 결과를 합산하여 최종 결과를 구합니다.
- 최적화 과정으로, 4개의 영역에서 동일한 결과(모두 1 또는 모두 0)라면 하나의 값으로 병합합니다.
시간 복잡도
- isUniform() 함수를 통해 특정 영역이 모두 동일한지 확인하는 데 최악의 경우 O(n^2) 시간이 소요됩니다.
- 배열을 4개로 나누는 과정이 반복되므로, 점화식은 T(n) = 4T(n/2) + O(n^2)로 표현됩니다.
- 마스터 정리에 의해 O(n^2)의 시간 복잡도를 가집니다.
구현 코드
function calc(a, b, c = 0) {
return Math.floor((a + b) / 2) + c;
}
function getCount(sy, sx, ey, ex, arr) {
if(sy === ey && sx === ex) {
return arr[sy - 1][sx - 1] === 1 ? [0, 1] : [1, 0];
}
let midY = calc(sy, ey);
let midX = calc(sx, ex);
const counts = [
getCount(sy, sx, midY, midX, arr),
getCount(sy, midX + 1, midY, ex, arr),
getCount(midY + 1, sx, ey, midX, arr),
getCount(midY + 1, midX + 1, ey, ex, arr)
];
let [zero, one] = counts.reduce(([z, o], [newZ, newO]) => [z + newZ, o + newO], [0, 0]);
if(one === 4 && zero === 0) {
return [0, 1];
} else if(one === 0 && zero === 4) {
return [1, 0];
}
return [zero, one];
}
function solution(arr) {
return getCount(1, 1, arr.length, arr.length, arr);
}