알고리즘
[Javascript] 프로그래머스 - 유사 칸토어 비트열
J3SUNG
2025. 3. 1. 22:51
728x90
문제 설명
유사 칸토어 비트열은 특정 규칙을 따라 생성되는 문자열입니다.
- 0번째 비트열은 "1"입니다.
- n번째 비트열은 이전 비트열에서 "1"을 "11011", "0"을 "00000"으로 치환하여 만듭니다.
이때, n번째 비트열에서 주어진 구간 [l, r] 내에 존재하는 "1"의 개수를 구하는 문제입니다.
제한 사항
- 1 ≤ n ≤ 20
- 1 ≤ l, r ≤ 5^n
- l ≤ r < l + 10,000,000
해결 방법
알고리즘: 분할 정복, 재귀
- 유사 칸토어 비트열은 5개의 구간으로 나뉘며, 가운데(3번째) 구간은 항상 "0"으로만 구성됩니다.
- 재귀적으로 n-1 비트열의 정보를 이용하여 l부터 r까지의 "1" 개수를 구합니다.
- n번째 비트열에서 각 부분이 차지하는 범위를 계산하고,
- 범위가 [l, r]과 겹치지 않으면 탐색하지 않음.
- 완전히 포함되면 사전 계산된 "1" 개수를 더함.
- 일부만 포함되면 더 작은 n-1 비트열로 범위를 좁혀 탐색.
- 최종적으로 모든 범위에서 "1"의 개수를 합산하여 반환합니다.
시간 복잡도
- 5의 지수승 크기의 비트열을 직접 생성하는 것은 비효율적이므로 분할 정복을 활용하여 탐색 범위를 줄임.
- 최악의 경우에도 O(log r) 수준에서 해결할 수 있음.
구현 코드
function getOne(l, r, n, offset = 0) {
if (n == 0) return 1;
let size = 5 ** (n - 1);
let count = 0;
for (let i = 0; i < 5; i++) {
let start = offset + i * size;
let end = start + size - 1;
if (end < l || start > r) continue;
if (i === 2) continue;
if (l <= start && end <= r) {
count += 4 ** (n - 1);
} else {
count += getOne(l, r, n - 1, start);
}
}
return count;
}
function solution(n, l, r) {
return getOne(l - 1, r - 1, n);
}